From fc9e4d35dd3d7da66d10a587a052558feee0397d Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 07:02:56 -0600
Subject: [PATCH 001/100] remove loading future

---
 .../address_book_views/address_book_view.dart | 221 +++++++++---------
 1 file changed, 112 insertions(+), 109 deletions(-)

diff --git a/lib/pages/address_book_views/address_book_view.dart b/lib/pages/address_book_views/address_book_view.dart
index 50e51110b..fd2a995cc 100644
--- a/lib/pages/address_book_views/address_book_view.dart
+++ b/lib/pages/address_book_views/address_book_view.dart
@@ -18,7 +18,6 @@ import 'package:stackwallet/widgets/address_book_card.dart';
 import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
-import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 import 'package:stackwallet/widgets/textfield_icon_button.dart';
@@ -38,9 +37,9 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
   late TextEditingController _searchController;
 
   final _searchFocusNode = FocusNode();
-
-  List<Contact>? _cache;
-  List<Contact>? _cacheFav;
+  //
+  // List<Contact>? _cache;
+  // List<Contact>? _cacheFav;
 
   String _searchTerm = "";
 
@@ -100,8 +99,10 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
   @override
   Widget build(BuildContext context) {
     debugPrint("BUILD: $runtimeType");
-    final addressBookEntriesFuture = ref.watch(
-        addressBookServiceProvider.select((value) => value.addressBookEntries));
+    // final addressBookEntriesFuture = ref.watch(
+    //     addressBookServiceProvider.select((value) => value.addressBookEntries));
+    final contacts =
+        ref.watch(addressBookServiceProvider.select((value) => value.contacts));
 
     final isDesktop = Util.isDesktop;
     return ConditionalParent(
@@ -279,57 +280,58 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
             const SizedBox(
               height: 12,
             ),
-            FutureBuilder(
-              future: addressBookEntriesFuture,
-              builder: (_, AsyncSnapshot<List<Contact>> snapshot) {
-                if (snapshot.connectionState == ConnectionState.done &&
-                    snapshot.hasData) {
-                  _cacheFav = snapshot.data!;
-                }
-                if (_cacheFav == null) {
-                  // TODO proper loading animation
-                  return const LoadingIndicator();
-                } else {
-                  if (_cacheFav!.isNotEmpty) {
-                    return RoundedWhiteContainer(
-                      padding: EdgeInsets.all(!isDesktop ? 0 : 15),
-                      child: Column(
-                        children: [
-                          ..._cacheFav!
-                              .where((element) => element.addresses
-                                  .where((e) => ref.watch(
-                                      addressBookFilterProvider.select(
-                                          (value) =>
-                                              value.coins.contains(e.coin))))
-                                  .isNotEmpty)
-                              .where((e) =>
-                                  e.isFavorite &&
-                                  ref
-                                      .read(addressBookServiceProvider)
-                                      .matches(_searchTerm, e))
-                              .where((element) => element.isFavorite)
-                              .map(
-                                (e) => AddressBookCard(
-                                  key: Key("favContactCard_${e.id}_key"),
-                                  contactId: e.id,
-                                ),
-                              ),
-                        ],
-                      ),
-                    );
-                  } else {
-                    return RoundedWhiteContainer(
-                      child: Center(
-                        child: Text(
-                          "Your favorite contacts will appear here",
-                          style: STextStyles.itemSubtitle(context),
+            // FutureBuilder(
+            //   future: addressBookEntriesFuture,
+            //   builder: (_, AsyncSnapshot<List<Contact>> snapshot) {
+            //     if (snapshot.connectionState == ConnectionState.done &&
+            //         snapshot.hasData) {
+            //       _cacheFav = snapshot.data!;
+            //     }
+            //     if (_cacheFav == null) {
+            //       // TODO proper loading animation
+            //       return const LoadingIndicator();
+            //     } else {
+            //       if (_cacheFav!.isNotEmpty) {
+            //         return
+            RoundedWhiteContainer(
+              padding: EdgeInsets.all(!isDesktop ? 0 : 15),
+              child: Column(
+                children: [
+                  ...contacts
+                      .where((element) => element.addresses
+                          .where((e) => ref.watch(addressBookFilterProvider
+                              .select((value) => value.coins.contains(e.coin))))
+                          .isNotEmpty)
+                      .where((e) =>
+                          e.isFavorite &&
+                          ref
+                              .read(addressBookServiceProvider)
+                              .matches(_searchTerm, e))
+                      .where((element) => element.isFavorite)
+                      .map(
+                        (e) => AddressBookCard(
+                          key: Key("favContactCard_${e.id}_key"),
+                          contactId: e.id,
                         ),
                       ),
-                    );
-                  }
-                }
-              },
-            ),
+                ],
+              ),
+            )
+            //         ;
+            //       } else {
+            //         return RoundedWhiteContainer(
+            //           child: Center(
+            //             child: Text(
+            //               "Your favorite contacts will appear here",
+            //               style: STextStyles.itemSubtitle(context),
+            //             ),
+            //           ),
+            //         );
+            //       }
+            //     }
+            //   },
+            // )
+            ,
             const SizedBox(
               height: 16,
             ),
@@ -340,63 +342,64 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
             const SizedBox(
               height: 12,
             ),
-            FutureBuilder(
-              future: addressBookEntriesFuture,
-              builder: (_, AsyncSnapshot<List<Contact>> snapshot) {
-                if (snapshot.connectionState == ConnectionState.done &&
-                    snapshot.hasData) {
-                  _cache = snapshot.data!;
-                }
-                if (_cache == null) {
-                  // TODO proper loading animation
-                  return const LoadingIndicator();
-                } else {
-                  if (_cache!.isNotEmpty) {
-                    return Column(
+            // FutureBuilder(
+            //   future: addressBookEntriesFuture,
+            //   builder: (_, AsyncSnapshot<List<Contact>> snapshot) {
+            //     if (snapshot.connectionState == ConnectionState.done &&
+            //         snapshot.hasData) {
+            //       _cache = snapshot.data!;
+            //     }
+            //     if (_cache == null) {
+            //       // TODO proper loading animation
+            //       return const LoadingIndicator();
+            //     } else {
+            //       if (_cache!.isNotEmpty) {
+            //         return
+            Column(
+              children: [
+                RoundedWhiteContainer(
+                  padding: EdgeInsets.all(!isDesktop ? 0 : 15),
+                  child: Padding(
+                    padding: const EdgeInsets.all(8.0),
+                    child: Column(
                       children: [
-                        RoundedWhiteContainer(
-                          padding: EdgeInsets.all(!isDesktop ? 0 : 15),
-                          child: Padding(
-                            padding: const EdgeInsets.all(8.0),
-                            child: Column(
-                              children: [
-                                ..._cache!
-                                    .where((element) => element.addresses
-                                        .where((e) => ref.watch(
-                                            addressBookFilterProvider.select(
-                                                (value) => value.coins
-                                                    .contains(e.coin))))
-                                        .isNotEmpty)
-                                    .where((e) => ref
-                                        .read(addressBookServiceProvider)
-                                        .matches(_searchTerm, e))
-                                    .where((element) => !element.isFavorite)
-                                    .map(
-                                      (e) => AddressBookCard(
-                                        key: Key(
-                                            "desktopContactCard_${e.id}_key"),
-                                        contactId: e.id,
-                                      ),
-                                    ),
-                              ],
+                        ...contacts
+                            .where((element) => element.addresses
+                                .where((e) => ref.watch(
+                                    addressBookFilterProvider.select((value) =>
+                                        value.coins.contains(e.coin))))
+                                .isNotEmpty)
+                            .where((e) => ref
+                                .read(addressBookServiceProvider)
+                                .matches(_searchTerm, e))
+                            .where((element) => !element.isFavorite)
+                            .map(
+                              (e) => AddressBookCard(
+                                key: Key("desktopContactCard_${e.id}_key"),
+                                contactId: e.id,
+                              ),
                             ),
-                          ),
-                        ),
                       ],
-                    );
-                  } else {
-                    return RoundedWhiteContainer(
-                      child: Center(
-                        child: Text(
-                          "Your contacts will appear here",
-                          style: STextStyles.itemSubtitle(context),
-                        ),
-                      ),
-                    );
-                  }
-                }
-              },
-            ),
+                    ),
+                  ),
+                ),
+              ],
+            )
+            //         ;
+            //       } else {
+            //         return RoundedWhiteContainer(
+            //           child: Center(
+            //             child: Text(
+            //               "Your contacts will appear here",
+            //               style: STextStyles.itemSubtitle(context),
+            //             ),
+            //           ),
+            //         );
+            //       }
+            //     }
+            //   },
+            // )
+            ,
           ],
         ),
       ),

From 7e2160d7ccf37fca61f918771ed7337b71fbd153 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 07:03:09 -0600
Subject: [PATCH 002/100] fix duplicate keys error

---
 .../address_book_views/subviews/contact_details_view.dart     | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/pages/address_book_views/subviews/contact_details_view.dart b/lib/pages/address_book_views/subviews/contact_details_view.dart
index c0c10b3b1..a48a535c6 100644
--- a/lib/pages/address_book_views/subviews/contact_details_view.dart
+++ b/lib/pages/address_book_views/subviews/contact_details_view.dart
@@ -469,7 +469,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
                               ..._cachedTransactions.map(
                                 (e) => TransactionCard(
                                   key: Key(
-                                      "contactDetailsTransaction_${e.item2.txid}_cardKey"),
+                                      "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey"),
                                   transaction: e.item2,
                                   walletId: e.item1,
                                 ),
@@ -499,7 +499,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
                               ..._cachedTransactions.map(
                                 (e) => TransactionCard(
                                   key: Key(
-                                      "contactDetailsTransaction_${e.item2.txid}_cardKey"),
+                                      "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey"),
                                   transaction: e.item2,
                                   walletId: e.item1,
                                 ),

From e0ef78685ddf9450ac62140544b74c4c8ce8b068 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 07:10:28 -0600
Subject: [PATCH 003/100] empty contacts list fix

---
 .../address_book_views/address_book_view.dart | 175 +++++++-----------
 1 file changed, 69 insertions(+), 106 deletions(-)

diff --git a/lib/pages/address_book_views/address_book_view.dart b/lib/pages/address_book_views/address_book_view.dart
index fd2a995cc..147e677e0 100644
--- a/lib/pages/address_book_views/address_book_view.dart
+++ b/lib/pages/address_book_views/address_book_view.dart
@@ -99,8 +99,6 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
   @override
   Widget build(BuildContext context) {
     debugPrint("BUILD: $runtimeType");
-    // final addressBookEntriesFuture = ref.watch(
-    //     addressBookServiceProvider.select((value) => value.addressBookEntries));
     final contacts =
         ref.watch(addressBookServiceProvider.select((value) => value.contacts));
 
@@ -280,58 +278,41 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
             const SizedBox(
               height: 12,
             ),
-            // FutureBuilder(
-            //   future: addressBookEntriesFuture,
-            //   builder: (_, AsyncSnapshot<List<Contact>> snapshot) {
-            //     if (snapshot.connectionState == ConnectionState.done &&
-            //         snapshot.hasData) {
-            //       _cacheFav = snapshot.data!;
-            //     }
-            //     if (_cacheFav == null) {
-            //       // TODO proper loading animation
-            //       return const LoadingIndicator();
-            //     } else {
-            //       if (_cacheFav!.isNotEmpty) {
-            //         return
-            RoundedWhiteContainer(
-              padding: EdgeInsets.all(!isDesktop ? 0 : 15),
-              child: Column(
-                children: [
-                  ...contacts
-                      .where((element) => element.addresses
-                          .where((e) => ref.watch(addressBookFilterProvider
-                              .select((value) => value.coins.contains(e.coin))))
-                          .isNotEmpty)
-                      .where((e) =>
-                          e.isFavorite &&
-                          ref
-                              .read(addressBookServiceProvider)
-                              .matches(_searchTerm, e))
-                      .where((element) => element.isFavorite)
-                      .map(
-                        (e) => AddressBookCard(
-                          key: Key("favContactCard_${e.id}_key"),
-                          contactId: e.id,
+            if (contacts.isNotEmpty)
+              RoundedWhiteContainer(
+                padding: EdgeInsets.all(!isDesktop ? 0 : 15),
+                child: Column(
+                  children: [
+                    ...contacts
+                        .where((element) => element.addresses
+                            .where((e) => ref.watch(
+                                addressBookFilterProvider.select(
+                                    (value) => value.coins.contains(e.coin))))
+                            .isNotEmpty)
+                        .where((e) =>
+                            e.isFavorite &&
+                            ref
+                                .read(addressBookServiceProvider)
+                                .matches(_searchTerm, e))
+                        .where((element) => element.isFavorite)
+                        .map(
+                          (e) => AddressBookCard(
+                            key: Key("favContactCard_${e.id}_key"),
+                            contactId: e.id,
+                          ),
                         ),
-                      ),
-                ],
+                  ],
+                ),
+              ),
+            if (contacts.isEmpty)
+              RoundedWhiteContainer(
+                child: Center(
+                  child: Text(
+                    "Your favorite contacts will appear here",
+                    style: STextStyles.itemSubtitle(context),
+                  ),
+                ),
               ),
-            )
-            //         ;
-            //       } else {
-            //         return RoundedWhiteContainer(
-            //           child: Center(
-            //             child: Text(
-            //               "Your favorite contacts will appear here",
-            //               style: STextStyles.itemSubtitle(context),
-            //             ),
-            //           ),
-            //         );
-            //       }
-            //     }
-            //   },
-            // )
-            ,
             const SizedBox(
               height: 16,
             ),
@@ -342,64 +323,46 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
             const SizedBox(
               height: 12,
             ),
-            // FutureBuilder(
-            //   future: addressBookEntriesFuture,
-            //   builder: (_, AsyncSnapshot<List<Contact>> snapshot) {
-            //     if (snapshot.connectionState == ConnectionState.done &&
-            //         snapshot.hasData) {
-            //       _cache = snapshot.data!;
-            //     }
-            //     if (_cache == null) {
-            //       // TODO proper loading animation
-            //       return const LoadingIndicator();
-            //     } else {
-            //       if (_cache!.isNotEmpty) {
-            //         return
-            Column(
-              children: [
-                RoundedWhiteContainer(
-                  padding: EdgeInsets.all(!isDesktop ? 0 : 15),
-                  child: Padding(
-                    padding: const EdgeInsets.all(8.0),
-                    child: Column(
-                      children: [
-                        ...contacts
-                            .where((element) => element.addresses
-                                .where((e) => ref.watch(
-                                    addressBookFilterProvider.select((value) =>
-                                        value.coins.contains(e.coin))))
-                                .isNotEmpty)
-                            .where((e) => ref
-                                .read(addressBookServiceProvider)
-                                .matches(_searchTerm, e))
-                            .where((element) => !element.isFavorite)
-                            .map(
-                              (e) => AddressBookCard(
-                                key: Key("desktopContactCard_${e.id}_key"),
-                                contactId: e.id,
+            if (contacts.isNotEmpty)
+              Column(
+                children: [
+                  RoundedWhiteContainer(
+                    padding: EdgeInsets.all(!isDesktop ? 0 : 15),
+                    child: Padding(
+                      padding: const EdgeInsets.all(8.0),
+                      child: Column(
+                        children: [
+                          ...contacts
+                              .where((element) => element.addresses
+                                  .where((e) => ref.watch(
+                                      addressBookFilterProvider.select(
+                                          (value) =>
+                                              value.coins.contains(e.coin))))
+                                  .isNotEmpty)
+                              .where((e) => ref
+                                  .read(addressBookServiceProvider)
+                                  .matches(_searchTerm, e))
+                              .map(
+                                (e) => AddressBookCard(
+                                  key: Key("desktopContactCard_${e.id}_key"),
+                                  contactId: e.id,
+                                ),
                               ),
-                            ),
-                      ],
+                        ],
+                      ),
                     ),
                   ),
+                ],
+              ),
+            if (contacts.isEmpty)
+              RoundedWhiteContainer(
+                child: Center(
+                  child: Text(
+                    "Your contacts will appear here",
+                    style: STextStyles.itemSubtitle(context),
+                  ),
                 ),
-              ],
-            )
-            //         ;
-            //       } else {
-            //         return RoundedWhiteContainer(
-            //           child: Center(
-            //             child: Text(
-            //               "Your contacts will appear here",
-            //               style: STextStyles.itemSubtitle(context),
-            //             ),
-            //           ),
-            //         );
-            //       }
-            //     }
-            //   },
-            // )
-            ,
+              ),
           ],
         ),
       ),

From 7cc3c71b0d1949401d79dcbe453b0dd3783a8a27 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 07:22:53 -0600
Subject: [PATCH 004/100] desktop addressbook search

---
 .../address_book_views/address_book_view.dart | 306 +++++++++---------
 .../desktop_address_book.dart                 |  14 +-
 2 files changed, 158 insertions(+), 162 deletions(-)

diff --git a/lib/pages/address_book_views/address_book_view.dart b/lib/pages/address_book_views/address_book_view.dart
index 147e677e0..35e2601e2 100644
--- a/lib/pages/address_book_views/address_book_view.dart
+++ b/lib/pages/address_book_views/address_book_view.dart
@@ -23,11 +23,16 @@ import 'package:stackwallet/widgets/stack_text_field.dart';
 import 'package:stackwallet/widgets/textfield_icon_button.dart';
 
 class AddressBookView extends ConsumerStatefulWidget {
-  const AddressBookView({Key? key, this.coin}) : super(key: key);
+  const AddressBookView({
+    Key? key,
+    this.coin,
+    this.filterTerm,
+  }) : super(key: key);
 
   static const String routeName = "/addressBook";
 
   final Coin? coin;
+  final String? filterTerm;
 
   @override
   ConsumerState<AddressBookView> createState() => _AddressBookViewState();
@@ -37,9 +42,6 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
   late TextEditingController _searchController;
 
   final _searchFocusNode = FocusNode();
-  //
-  // List<Contact>? _cache;
-  // List<Contact>? _cacheFav;
 
   String _searchTerm = "";
 
@@ -198,7 +200,12 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
                     child: IntrinsicHeight(
                       child: Padding(
                         padding: const EdgeInsets.all(4),
-                        child: child,
+                        child: ConstrainedBox(
+                          constraints: BoxConstraints(
+                            minHeight: MediaQuery.of(context).size.height - 271,
+                          ),
+                          child: child,
+                        ),
                       ),
                     ),
                   ),
@@ -208,163 +215,156 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
           ),
         );
       },
-      child: ConstrainedBox(
-        constraints: BoxConstraints(
-          minHeight: MediaQuery.of(context).size.height - 271,
-        ),
-        child: Column(
-          crossAxisAlignment: CrossAxisAlignment.stretch,
-          children: [
-            ClipRRect(
-              borderRadius: BorderRadius.circular(
-                Constants.size.circularBorderRadius,
-              ),
-              child: !isDesktop
-                  ? TextField(
-                      autocorrect: Util.isDesktop ? false : true,
-                      enableSuggestions: Util.isDesktop ? false : true,
-                      controller: _searchController,
-                      focusNode: _searchFocusNode,
-                      onChanged: (value) {
-                        setState(() {
-                          _searchTerm = value;
-                        });
-                      },
-                      style: STextStyles.field(context),
-                      decoration: standardInputDecoration(
-                        "Search",
-                        _searchFocusNode,
-                        context,
-                      ).copyWith(
-                        prefixIcon: Padding(
-                          padding: const EdgeInsets.symmetric(
-                            horizontal: 10,
-                            vertical: 16,
-                          ),
-                          child: SvgPicture.asset(
-                            Assets.svg.search,
-                            width: 16,
-                            height: 16,
-                          ),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.stretch,
+        children: [
+          ClipRRect(
+            borderRadius: BorderRadius.circular(
+              Constants.size.circularBorderRadius,
+            ),
+            child: !isDesktop
+                ? TextField(
+                    autocorrect: Util.isDesktop ? false : true,
+                    enableSuggestions: Util.isDesktop ? false : true,
+                    controller: _searchController,
+                    focusNode: _searchFocusNode,
+                    onChanged: (value) {
+                      setState(() {
+                        _searchTerm = value;
+                      });
+                    },
+                    style: STextStyles.field(context),
+                    decoration: standardInputDecoration(
+                      "Search",
+                      _searchFocusNode,
+                      context,
+                    ).copyWith(
+                      prefixIcon: Padding(
+                        padding: const EdgeInsets.symmetric(
+                          horizontal: 10,
+                          vertical: 16,
+                        ),
+                        child: SvgPicture.asset(
+                          Assets.svg.search,
+                          width: 16,
+                          height: 16,
                         ),
-                        suffixIcon: _searchController.text.isNotEmpty
-                            ? Padding(
-                                padding: const EdgeInsets.only(right: 0),
-                                child: UnconstrainedBox(
-                                  child: Row(
-                                    children: [
-                                      TextFieldIconButton(
-                                        child: const XIcon(),
-                                        onTap: () async {
-                                          setState(() {
-                                            _searchController.text = "";
-                                          });
-                                        },
-                                      ),
-                                    ],
-                                  ),
-                                ),
-                              )
-                            : null,
                       ),
-                    )
-                  : null,
-            ),
-            if (!isDesktop) const SizedBox(height: 16),
-            Text(
-              "Favorites",
-              style: STextStyles.smallMed12(context),
-            ),
-            const SizedBox(
-              height: 12,
-            ),
-            if (contacts.isNotEmpty)
-              RoundedWhiteContainer(
-                padding: EdgeInsets.all(!isDesktop ? 0 : 15),
-                child: Column(
-                  children: [
-                    ...contacts
-                        .where((element) => element.addresses
-                            .where((e) => ref.watch(
-                                addressBookFilterProvider.select(
-                                    (value) => value.coins.contains(e.coin))))
-                            .isNotEmpty)
-                        .where((e) =>
-                            e.isFavorite &&
-                            ref
-                                .read(addressBookServiceProvider)
-                                .matches(_searchTerm, e))
-                        .where((element) => element.isFavorite)
-                        .map(
-                          (e) => AddressBookCard(
-                            key: Key("favContactCard_${e.id}_key"),
-                            contactId: e.id,
-                          ),
-                        ),
-                  ],
-                ),
-              ),
-            if (contacts.isEmpty)
-              RoundedWhiteContainer(
-                child: Center(
-                  child: Text(
-                    "Your favorite contacts will appear here",
-                    style: STextStyles.itemSubtitle(context),
-                  ),
-                ),
-              ),
-            const SizedBox(
-              height: 16,
-            ),
-            Text(
-              "All contacts",
-              style: STextStyles.smallMed12(context),
-            ),
-            const SizedBox(
-              height: 12,
-            ),
-            if (contacts.isNotEmpty)
-              Column(
-                children: [
-                  RoundedWhiteContainer(
-                    padding: EdgeInsets.all(!isDesktop ? 0 : 15),
-                    child: Padding(
-                      padding: const EdgeInsets.all(8.0),
-                      child: Column(
-                        children: [
-                          ...contacts
-                              .where((element) => element.addresses
-                                  .where((e) => ref.watch(
-                                      addressBookFilterProvider.select(
-                                          (value) =>
-                                              value.coins.contains(e.coin))))
-                                  .isNotEmpty)
-                              .where((e) => ref
-                                  .read(addressBookServiceProvider)
-                                  .matches(_searchTerm, e))
-                              .map(
-                                (e) => AddressBookCard(
-                                  key: Key("desktopContactCard_${e.id}_key"),
-                                  contactId: e.id,
+                      suffixIcon: _searchController.text.isNotEmpty
+                          ? Padding(
+                              padding: const EdgeInsets.only(right: 0),
+                              child: UnconstrainedBox(
+                                child: Row(
+                                  children: [
+                                    TextFieldIconButton(
+                                      child: const XIcon(),
+                                      onTap: () async {
+                                        setState(() {
+                                          _searchController.text = "";
+                                        });
+                                      },
+                                    ),
+                                  ],
                                 ),
                               ),
-                        ],
-                      ),
+                            )
+                          : null,
                     ),
-                  ),
+                  )
+                : null,
+          ),
+          if (!isDesktop) const SizedBox(height: 16),
+          Text(
+            "Favorites",
+            style: STextStyles.smallMed12(context),
+          ),
+          const SizedBox(
+            height: 12,
+          ),
+          if (contacts.isNotEmpty)
+            RoundedWhiteContainer(
+              padding: EdgeInsets.all(!isDesktop ? 0 : 15),
+              child: Column(
+                children: [
+                  ...contacts
+                      .where((element) => element.addresses
+                          .where((e) => ref.watch(addressBookFilterProvider
+                              .select((value) => value.coins.contains(e.coin))))
+                          .isNotEmpty)
+                      .where((e) =>
+                          e.isFavorite &&
+                          ref
+                              .read(addressBookServiceProvider)
+                              .matches(widget.filterTerm ?? _searchTerm, e))
+                      .where((element) => element.isFavorite)
+                      .map(
+                        (e) => AddressBookCard(
+                          key: Key("favContactCard_${e.id}_key"),
+                          contactId: e.id,
+                        ),
+                      ),
                 ],
               ),
-            if (contacts.isEmpty)
-              RoundedWhiteContainer(
-                child: Center(
-                  child: Text(
-                    "Your contacts will appear here",
-                    style: STextStyles.itemSubtitle(context),
-                  ),
+            ),
+          if (contacts.isEmpty)
+            RoundedWhiteContainer(
+              child: Center(
+                child: Text(
+                  "Your favorite contacts will appear here",
+                  style: STextStyles.itemSubtitle(context),
                 ),
               ),
-          ],
-        ),
+            ),
+          const SizedBox(
+            height: 16,
+          ),
+          Text(
+            "All contacts",
+            style: STextStyles.smallMed12(context),
+          ),
+          const SizedBox(
+            height: 12,
+          ),
+          if (contacts.isNotEmpty)
+            Column(
+              children: [
+                RoundedWhiteContainer(
+                  padding: EdgeInsets.all(!isDesktop ? 0 : 15),
+                  child: Padding(
+                    padding: const EdgeInsets.all(8.0),
+                    child: Column(
+                      children: [
+                        ...contacts
+                            .where((element) => element.addresses
+                                .where((e) => ref.watch(
+                                    addressBookFilterProvider.select((value) =>
+                                        value.coins.contains(e.coin))))
+                                .isNotEmpty)
+                            .where((e) => ref
+                                .read(addressBookServiceProvider)
+                                .matches(widget.filterTerm ?? _searchTerm, e))
+                            .map(
+                              (e) => AddressBookCard(
+                                key: Key("desktopContactCard_${e.id}_key"),
+                                contactId: e.id,
+                              ),
+                            ),
+                      ],
+                    ),
+                  ),
+                ),
+              ],
+            ),
+          if (contacts.isEmpty)
+            RoundedWhiteContainer(
+              child: Center(
+                child: Text(
+                  "Your contacts will appear here",
+                  style: STextStyles.itemSubtitle(context),
+                ),
+              ),
+            ),
+        ],
       ),
     );
   }
diff --git a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
index ec40e5f60..d561de946 100644
--- a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
@@ -1,11 +1,9 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/svg.dart';
-import 'package:stackwallet/models/contact.dart';
 import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
 import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart';
 import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart';
-import 'package:stackwallet/providers/global/wallets_provider.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
@@ -34,11 +32,6 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
 
   late final FocusNode _searchFocusNode;
 
-  List<Contact>? _cache;
-  List<Contact>? _cacheFav;
-
-  late bool hasContacts = false;
-
   String _searchTerm = "";
 
   Future<void> selectCryptocurrency() async {
@@ -90,7 +83,6 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
   @override
   Widget build(BuildContext context) {
     debugPrint("BUILD: $runtimeType");
-    final hasWallets = ref.watch(walletsChangeNotifierProvider).hasWallets;
 
     return DesktopScaffold(
       appBar: DesktopAppBar(
@@ -171,7 +163,11 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
                   const SizedBox(
                     height: 24,
                   ),
-                  const AddressBookView(),
+                  Expanded(
+                    child: AddressBookView(
+                      filterTerm: _searchTerm,
+                    ),
+                  ),
                 ],
               ),
             ),

From 49103c86f1b63bd56563a0aa1167bcda5ee69cd8 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 09:00:10 -0600
Subject: [PATCH 005/100] desktop addressbook layout fix

---
 .../desktop_address_book.dart                 | 442 +++++++++++++-----
 1 file changed, 338 insertions(+), 104 deletions(-)

diff --git a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
index d561de946..abb797aac 100644
--- a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
@@ -1,23 +1,31 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/svg.dart';
-import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
+import 'package:stackwallet/models/contact.dart';
+import 'package:stackwallet/models/contact_address_entry.dart';
 import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart';
 import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart';
+import 'package:stackwallet/providers/global/address_book_service_provider.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/constants.dart';
+import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/address_book_card.dart';
 import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 import 'package:stackwallet/widgets/textfield_icon_button.dart';
 
+import '../../../providers/providers.dart';
+import '../../../providers/ui/address_book_providers/address_book_filter_provider.dart';
+
 class DesktopAddressBook extends ConsumerStatefulWidget {
   const DesktopAddressBook({Key? key}) : super(key: key);
 
@@ -69,6 +77,46 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
     _searchController = TextEditingController();
     _searchFocusNode = FocusNode();
 
+    ref.refresh(addressBookFilterProvider);
+
+    // if (widget.coin == null) {
+    List<Coin> coins = Coin.values.where((e) => !(e == Coin.epicCash)).toList();
+    coins.remove(Coin.firoTestNet);
+
+    bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins;
+
+    if (showTestNet) {
+      ref.read(addressBookFilterProvider).addAll(coins, false);
+    } else {
+      ref.read(addressBookFilterProvider).addAll(
+          coins.getRange(0, coins.length - kTestNetCoinCount + 1), false);
+    }
+    // } else {
+    //   ref.read(addressBookFilterProvider).add(widget.coin!, false);
+    // }
+
+    WidgetsBinding.instance.addPostFrameCallback((_) async {
+      List<ContactAddressEntry> addresses = [];
+      final managers = ref.read(walletsChangeNotifierProvider).managers;
+      for (final manager in managers) {
+        addresses.add(
+          ContactAddressEntry(
+            coin: manager.coin,
+            address: await manager.currentReceivingAddress,
+            label: "Current Receiving",
+            other: manager.walletName,
+          ),
+        );
+      }
+      final self = Contact(
+        name: "My Stack",
+        addresses: addresses,
+        isFavorite: true,
+        id: "default",
+      );
+      await ref.read(addressBookServiceProvider).editContact(self);
+    });
+
     super.initState();
   }
 
@@ -83,6 +131,32 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
   @override
   Widget build(BuildContext context) {
     debugPrint("BUILD: $runtimeType");
+    final contacts =
+        ref.watch(addressBookServiceProvider.select((value) => value.contacts));
+
+    final allContacts = contacts
+        .where((element) => element.addresses
+            .where((e) => ref.watch(addressBookFilterProvider
+                .select((value) => value.coins.contains(e.coin))))
+            .isNotEmpty)
+        .where((e) =>
+            ref.read(addressBookServiceProvider).matches(_searchTerm, e));
+
+    final favorites = contacts
+        .where((element) => element.addresses
+            .where((e) => ref.watch(addressBookFilterProvider
+                .select((value) => value.coins.contains(e.coin))))
+            .isNotEmpty)
+        .where((e) =>
+            e.isFavorite &&
+            ref.read(addressBookServiceProvider).matches(_searchTerm, e))
+        .where((element) => element.isFavorite);
+
+    print("=========================================================");
+    print("contacts: ${contacts.length}");
+    print("favorites: ${favorites.length}");
+    print("allContacts: ${allContacts.length}");
+    print("=========================================================");
 
     return DesktopScaffold(
       appBar: DesktopAppBar(
@@ -100,121 +174,281 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
         ),
       ),
       body: Padding(
-        padding: const EdgeInsets.all(24),
-        child: Row(
+        padding: const EdgeInsets.only(
+          left: 24,
+          right: 24,
+          bottom: 24,
+        ),
+        child: DesktopAddressBookScaffold(
+          controlsLeft: ClipRRect(
+            borderRadius: BorderRadius.circular(
+              Constants.size.circularBorderRadius,
+            ),
+            child: TextField(
+              autocorrect: Util.isDesktop ? false : true,
+              enableSuggestions: Util.isDesktop ? false : true,
+              controller: _searchController,
+              focusNode: _searchFocusNode,
+              onChanged: (value) {
+                setState(() {
+                  _searchTerm = value;
+                });
+              },
+              style: STextStyles.field(context),
+              decoration: standardInputDecoration(
+                "Search",
+                _searchFocusNode,
+                context,
+              ).copyWith(
+                prefixIcon: Padding(
+                  padding: const EdgeInsets.symmetric(
+                    horizontal: 10,
+                    vertical: 20,
+                  ),
+                  child: SvgPicture.asset(
+                    Assets.svg.search,
+                    width: 16,
+                    height: 16,
+                  ),
+                ),
+                suffixIcon: _searchController.text.isNotEmpty
+                    ? Padding(
+                        padding: const EdgeInsets.only(right: 0),
+                        child: UnconstrainedBox(
+                          child: Row(
+                            children: [
+                              TextFieldIconButton(
+                                child: const XIcon(),
+                                onTap: () async {
+                                  setState(() {
+                                    _searchController.text = "";
+                                  });
+                                },
+                              ),
+                            ],
+                          ),
+                        ),
+                      )
+                    : null,
+              ),
+            ),
+          ),
+          controlsRight: Row(
+            mainAxisAlignment: MainAxisAlignment.end,
+            children: [
+              SecondaryButton(
+                width: 184,
+                label: "Filter",
+                desktopMed: true,
+                icon: SvgPicture.asset(
+                  Assets.svg.filter,
+                  color: Theme.of(context)
+                      .extension<StackColors>()!
+                      .buttonTextSecondary,
+                ),
+                onPressed: selectCryptocurrency,
+              ),
+              const SizedBox(
+                width: 20,
+              ),
+              PrimaryButton(
+                width: 184,
+                label: "Add new",
+                desktopMed: true,
+                icon: SvgPicture.asset(
+                  Assets.svg.circlePlus,
+                  color: Theme.of(context)
+                      .extension<StackColors>()!
+                      .buttonTextPrimary,
+                ),
+                onPressed: newContact,
+              ),
+            ],
+          ),
+          filterItems: Container(),
+          upperLabel: favorites.isEmpty && allContacts.isEmpty
+              ? null
+              : Text(
+                  favorites.isEmpty ? "All contacts" : "Favorites",
+                  style: STextStyles.smallMed12(context),
+                ),
+          lowerLabel: favorites.isEmpty
+              ? null
+              : Padding(
+                  padding: const EdgeInsets.only(
+                    top: 20,
+                    bottom: 12,
+                  ),
+                  child: Text(
+                    "All contacts",
+                    style: STextStyles.smallMed12(context),
+                  ),
+                ),
+          favorites: favorites.isNotEmpty
+              ? RoundedWhiteContainer(
+                  padding: const EdgeInsets.all(0),
+                  child: Column(
+                    children: [
+                      ...favorites.map(
+                        (e) => AddressBookCard(
+                          key: Key("favContactCard_${e.id}_key"),
+                          contactId: e.id,
+                        ),
+                      ),
+                    ],
+                  ),
+                )
+              : RoundedWhiteContainer(
+                  child: Center(
+                    child: Text(
+                      "Your favorite contacts will appear here",
+                      style: STextStyles.itemSubtitle(context),
+                    ),
+                  ),
+                ),
+          all: allContacts.isNotEmpty
+              ? Column(
+                  children: [
+                    RoundedWhiteContainer(
+                      padding: const EdgeInsets.all(0),
+                      child: Padding(
+                        padding: const EdgeInsets.all(8.0),
+                        child: Column(
+                          children: [
+                            ...allContacts.map(
+                              (e) => AddressBookCard(
+                                key: Key("desktopContactCard_${e.id}_key"),
+                                contactId: e.id,
+                              ),
+                            ),
+                          ],
+                        ),
+                      ),
+                    ),
+                  ],
+                )
+              : RoundedWhiteContainer(
+                  child: Center(
+                    child: Text(
+                      "Your contacts will appear here",
+                      style: STextStyles.itemSubtitle(context),
+                    ),
+                  ),
+                ),
+          details: Container(
+            color: Colors.purple,
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+class DesktopAddressBookScaffold extends StatelessWidget {
+  const DesktopAddressBookScaffold({
+    Key? key,
+    required this.controlsLeft,
+    required this.controlsRight,
+    required this.filterItems,
+    required this.upperLabel,
+    required this.lowerLabel,
+    required this.favorites,
+    required this.all,
+    required this.details,
+  }) : super(key: key);
+
+  final Widget? controlsLeft;
+  final Widget? controlsRight;
+  final Widget? filterItems;
+  final Widget? upperLabel;
+  final Widget? lowerLabel;
+  final Widget? favorites;
+  final Widget? all;
+  final Widget? details;
+
+  static const double weirdRowHeight = 30;
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        Row(
+          mainAxisAlignment: MainAxisAlignment.end,
           children: [
             Expanded(
               flex: 6,
-              child: Column(
-                children: [
-                  ClipRRect(
-                    borderRadius: BorderRadius.circular(
-                      Constants.size.circularBorderRadius,
-                    ),
-                    child: TextField(
-                      autocorrect: Util.isDesktop ? false : true,
-                      enableSuggestions: Util.isDesktop ? false : true,
-                      controller: _searchController,
-                      focusNode: _searchFocusNode,
-                      onChanged: (value) {
-                        setState(() {
-                          _searchTerm = value;
-                        });
-                      },
-                      style: STextStyles.field(context),
-                      decoration: standardInputDecoration(
-                        "Search",
-                        _searchFocusNode,
-                        context,
-                      ).copyWith(
-                        prefixIcon: Padding(
-                          padding: const EdgeInsets.symmetric(
-                            horizontal: 10,
-                            vertical: 20,
-                          ),
-                          child: SvgPicture.asset(
-                            Assets.svg.search,
-                            width: 16,
-                            height: 16,
-                          ),
-                        ),
-                        suffixIcon: _searchController.text.isNotEmpty
-                            ? Padding(
-                                padding: const EdgeInsets.only(right: 0),
-                                child: UnconstrainedBox(
-                                  child: Row(
-                                    children: [
-                                      TextFieldIconButton(
-                                        child: const XIcon(),
-                                        onTap: () async {
-                                          setState(() {
-                                            _searchController.text = "";
-                                          });
-                                        },
-                                      ),
-                                    ],
-                                  ),
-                                ),
-                              )
-                            : null,
-                      ),
-                    ),
-                  ),
-                  const SizedBox(
-                    height: 24,
-                  ),
-                  Expanded(
-                    child: AddressBookView(
-                      filterTerm: _searchTerm,
-                    ),
-                  ),
-                ],
-              ),
+              child: controlsLeft ?? Container(),
             ),
             const SizedBox(
               width: 20,
             ),
             Expanded(
               flex: 5,
-              child: Column(
-                children: [
-                  Row(
-                    children: [
-                      SecondaryButton(
-                        width: 184,
-                        label: "Filter",
-                        desktopMed: true,
-                        icon: SvgPicture.asset(
-                          Assets.svg.filter,
-                          color: Theme.of(context)
-                              .extension<StackColors>()!
-                              .buttonTextSecondary,
-                        ),
-                        onPressed: selectCryptocurrency,
-                      ),
-                      const SizedBox(
-                        width: 20,
-                      ),
-                      PrimaryButton(
-                        width: 184,
-                        label: "Add new",
-                        desktopMed: true,
-                        icon: SvgPicture.asset(
-                          Assets.svg.circlePlus,
-                          color: Theme.of(context)
-                              .extension<StackColors>()!
-                              .buttonTextPrimary,
-                        ),
-                        onPressed: newContact,
-                      ),
-                    ],
-                  ),
-                ],
-              ),
+              child: controlsRight ?? Container(),
             ),
           ],
         ),
-      ),
+        const SizedBox(
+          height: 20,
+        ),
+        Row(
+          children: [
+            Expanded(
+              child: filterItems ?? Container(),
+            ),
+          ],
+        ),
+        Expanded(
+          child: Row(
+            children: [
+              Expanded(
+                flex: 6,
+                child: LayoutBuilder(
+                  builder: (context, constraints) {
+                    return SingleChildScrollView(
+                      child: ConstrainedBox(
+                        constraints: BoxConstraints(
+                          minHeight: constraints.maxHeight,
+                        ),
+                        child: IntrinsicHeight(
+                          child: Column(
+                            crossAxisAlignment: CrossAxisAlignment.start,
+                            children: [
+                              SizedBox(
+                                height: weirdRowHeight,
+                                child: upperLabel,
+                              ),
+                              favorites ?? Container(),
+                              lowerLabel ?? Container(),
+                              all ?? Container(),
+                            ],
+                          ),
+                        ),
+                      ),
+                    );
+                  },
+                ),
+              ),
+              const SizedBox(
+                width: 20,
+              ),
+              Expanded(
+                flex: 5,
+                child: Column(
+                  children: [
+                    const SizedBox(
+                      height: weirdRowHeight,
+                    ),
+                    Expanded(
+                      child: details ?? Container(),
+                    ),
+                  ],
+                ),
+              ),
+            ],
+          ),
+        )
+      ],
     );
   }
 }

From 8c0a6f5669de3d0bf4aa8b6c5329ff4d09e6bc30 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 09:04:54 -0600
Subject: [PATCH 006/100]  address book search fixes

---
 .../address_book_views/address_book_view.dart |  1 +
 .../desktop_address_book.dart                 | 51 +++++++++----------
 2 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/lib/pages/address_book_views/address_book_view.dart b/lib/pages/address_book_views/address_book_view.dart
index 35e2601e2..cdc9fb5b7 100644
--- a/lib/pages/address_book_views/address_book_view.dart
+++ b/lib/pages/address_book_views/address_book_view.dart
@@ -261,6 +261,7 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
                                       onTap: () async {
                                         setState(() {
                                           _searchController.text = "";
+                                          _searchTerm = "";
                                         });
                                       },
                                     ),
diff --git a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
index abb797aac..51b075284 100644
--- a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
@@ -152,12 +152,6 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
             ref.read(addressBookServiceProvider).matches(_searchTerm, e))
         .where((element) => element.isFavorite);
 
-    print("=========================================================");
-    print("contacts: ${contacts.length}");
-    print("favorites: ${favorites.length}");
-    print("allContacts: ${allContacts.length}");
-    print("=========================================================");
-
     return DesktopScaffold(
       appBar: DesktopAppBar(
         isCompactHeight: true,
@@ -222,6 +216,7 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
                                 onTap: () async {
                                   setState(() {
                                     _searchController.text = "";
+                                    _searchTerm = "";
                                   });
                                 },
                               ),
@@ -284,8 +279,18 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
                     style: STextStyles.smallMed12(context),
                   ),
                 ),
-          favorites: favorites.isNotEmpty
-              ? RoundedWhiteContainer(
+          favorites: favorites.isEmpty
+              ? contacts.isNotEmpty
+                  ? null
+                  : RoundedWhiteContainer(
+                      child: Center(
+                        child: Text(
+                          "Your favorite contacts will appear here",
+                          style: STextStyles.itemSubtitle(context),
+                        ),
+                      ),
+                    )
+              : RoundedWhiteContainer(
                   padding: const EdgeInsets.all(0),
                   child: Column(
                     children: [
@@ -297,17 +302,19 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
                       ),
                     ],
                   ),
-                )
-              : RoundedWhiteContainer(
-                  child: Center(
-                    child: Text(
-                      "Your favorite contacts will appear here",
-                      style: STextStyles.itemSubtitle(context),
-                    ),
-                  ),
                 ),
-          all: allContacts.isNotEmpty
-              ? Column(
+          all: allContacts.isEmpty
+              ? contacts.isNotEmpty
+                  ? null
+                  : RoundedWhiteContainer(
+                      child: Center(
+                        child: Text(
+                          "Your contacts will appear here",
+                          style: STextStyles.itemSubtitle(context),
+                        ),
+                      ),
+                    )
+              : Column(
                   children: [
                     RoundedWhiteContainer(
                       padding: const EdgeInsets.all(0),
@@ -326,14 +333,6 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
                       ),
                     ),
                   ],
-                )
-              : RoundedWhiteContainer(
-                  child: Center(
-                    child: Text(
-                      "Your contacts will appear here",
-                      style: STextStyles.itemSubtitle(context),
-                    ),
-                  ),
                 ),
           details: Container(
             color: Colors.purple,

From 72248d6a644807d6f7410c31529ae3a57869066f Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 10:12:19 -0600
Subject: [PATCH 007/100] expandable fix

---
 .../wallet_network_settings_view.dart                  | 10 +++++-----
 .../sub_widgets/contact_list_item.dart                 |  2 +-
 lib/widgets/expandable.dart                            |  6 +++---
 lib/widgets/node_card.dart                             |  6 +++---
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart
index accf244eb..3044467aa 100644
--- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart
+++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart
@@ -77,7 +77,7 @@ class _WalletNetworkSettingsViewState
 
   late double _percent;
   late int _blocksRemaining;
-  bool _advancedIsExpanded = true;
+  bool _advancedIsExpanded = false;
 
   Future<void> _attemptRescan() async {
     if (!Platform.isLinux) await Wakelock.enable();
@@ -855,8 +855,8 @@ class _WalletNetworkSettingsViewState
                     ),
                     SvgPicture.asset(
                       _advancedIsExpanded
-                          ? Assets.svg.chevronDown
-                          : Assets.svg.chevronUp,
+                          ? Assets.svg.chevronUp
+                          : Assets.svg.chevronDown,
                       width: 12,
                       height: 6,
                       color: Theme.of(context)
@@ -877,11 +877,11 @@ class _WalletNetworkSettingsViewState
                         text: "Rescan",
                         onTap: () async {
                           await Navigator.of(context).push(
-                             FadePageRoute<void>(
+                            FadePageRoute<void>(
                               ConfirmFullRescanDialog(
                                 onConfirm: _attemptRescan,
                               ),
-                             const RouteSettings(),
+                              const RouteSettings(),
                             ),
                           );
                           // await showDialog<dynamic>(
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart
index e030f9882..7acfaae9e 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart
@@ -58,7 +58,7 @@ class _ContactListItemState extends ConsumerState<ContactListItem> {
           ),
           child: AddressBookCard(
             contactId: contactId,
-            indicatorDown: _state == ExpandableState.expanded,
+            indicatorDown: _state,
           ),
         ),
         body: Column(
diff --git a/lib/widgets/expandable.dart b/lib/widgets/expandable.dart
index 47726d6d6..737f4ce7d 100644
--- a/lib/widgets/expandable.dart
+++ b/lib/widgets/expandable.dart
@@ -1,8 +1,8 @@
 import 'package:flutter/material.dart';
 
 enum ExpandableState {
-  expanded,
   collapsed,
+  expanded,
 }
 
 class ExpandableController {
@@ -45,11 +45,11 @@ class _ExpandableState extends State<Expandable> with TickerProviderStateMixin {
   Future<void> toggle() async {
     if (animation.isDismissed) {
       await animationController.forward();
-      _toggleState = ExpandableState.collapsed;
+      _toggleState = ExpandableState.expanded;
       widget.onExpandChanged?.call(_toggleState);
     } else if (animation.isCompleted) {
       await animationController.reverse();
-      _toggleState = ExpandableState.expanded;
+      _toggleState = ExpandableState.collapsed;
       widget.onExpandChanged?.call(_toggleState);
     }
     controller?.state = _toggleState;
diff --git a/lib/widgets/node_card.dart b/lib/widgets/node_card.dart
index 1da7e9012..c3fb36c70 100644
--- a/lib/widgets/node_card.dart
+++ b/lib/widgets/node_card.dart
@@ -46,7 +46,7 @@ class NodeCard extends ConsumerStatefulWidget {
 class _NodeCardState extends ConsumerState<NodeCard> {
   String _status = "Disconnected";
   late final String nodeId;
-  bool _advancedIsExpanded = true;
+  bool _advancedIsExpanded = false;
 
   Future<void> _notifyWalletsOfUpdatedNode(WidgetRef ref) async {
     final managers = ref
@@ -367,8 +367,8 @@ class _NodeCardState extends ConsumerState<NodeCard> {
                 if (isDesktop)
                   SvgPicture.asset(
                     _advancedIsExpanded
-                        ? Assets.svg.chevronDown
-                        : Assets.svg.chevronUp,
+                        ? Assets.svg.chevronUp
+                        : Assets.svg.chevronDown,
                     width: 12,
                     height: 6,
                     color: Theme.of(context)

From df810c2a1449458e046aa994960b2ccdd5cbeecb Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 10:12:38 -0600
Subject: [PATCH 008/100] "send from" contacts fix

---
 .../address_book_address_chooser.dart         | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart
index 9f309a08e..92dd9f6fc 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart
@@ -200,12 +200,19 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
 
                 final favorites = pullOutFavorites(contacts);
 
-                return ListView.builder(
+                final totalLength = favorites.length +
+                    contacts.length +
+                    2; // +2 for "fav" and "all" headers
+
+                return ListView.separated(
                   primary: false,
                   shrinkWrap: true,
-                  itemCount: favorites.length +
-                      contacts.length +
-                      2, // +2 for "fav" and "all" headers
+                  itemCount: totalLength,
+                  separatorBuilder: (context, index) {
+                    return const SizedBox(
+                      height: 10,
+                    );
+                  },
                   itemBuilder: (context, index) {
                     if (index == 0) {
                       return Padding(
@@ -220,7 +227,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
                               STextStyles.desktopTextExtraExtraSmall(context),
                         ),
                       );
-                    } else if (index <= favorites.length) {
+                    } else if (index < favorites.length + 1) {
                       final id = favorites[index - 1].id;
                       return ContactListItem(
                         key: Key("contactContactListItem_${id}_key"),
@@ -241,7 +248,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
                         ),
                       );
                     } else {
-                      final id = contacts[index - favorites.length - 1].id;
+                      final id = contacts[index - favorites.length - 2].id;
                       return ContactListItem(
                         key: Key("contactContactListItem_${id}_key"),
                         contactId: id,

From b988342bb146d1085f64527b4ce28f7765532c6f Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 10:12:59 -0600
Subject: [PATCH 009/100] "send from" contact card fix

---
 lib/widgets/address_book_card.dart | 185 +++++++++++++++--------------
 1 file changed, 95 insertions(+), 90 deletions(-)

diff --git a/lib/widgets/address_book_card.dart b/lib/widgets/address_book_card.dart
index c9ac86052..329e35fdf 100644
--- a/lib/widgets/address_book_card.dart
+++ b/lib/widgets/address_book_card.dart
@@ -9,6 +9,8 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
+import 'package:stackwallet/widgets/expandable.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 
 class AddressBookCard extends ConsumerStatefulWidget {
@@ -19,7 +21,7 @@ class AddressBookCard extends ConsumerStatefulWidget {
   }) : super(key: key);
 
   final String contactId;
-  final bool? indicatorDown;
+  final ExpandableState? indicatorDown;
 
   @override
   ConsumerState<AddressBookCard> createState() => _AddressBookCardState();
@@ -58,108 +60,111 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
       }
     }
 
-    return RoundedWhiteContainer(
-      padding: const EdgeInsets.all(4),
-      child: RawMaterialButton(
-        // splashColor: Theme.of(context).extension<StackColors>()!.highlight,
-        padding: const EdgeInsets.all(0),
-        materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
-        shape: RoundedRectangleBorder(
-          borderRadius: BorderRadius.circular(
-            Constants.size.circularBorderRadius,
-          ),
-        ),
-        onPressed: () {
-          showDialog<void>(
-            context: context,
-            useSafeArea: true,
-            barrierDismissible: true,
-            builder: (_) => ContactPopUp(
-              contactId: contact.id,
+    return ConditionalParent(
+      condition: !isDesktop,
+      child: Row(
+        children: [
+          Container(
+            width: 32,
+            height: 32,
+            decoration: BoxDecoration(
+              color: contact.id == "default"
+                  ? Theme.of(context)
+                      .extension<StackColors>()!
+                      .myStackContactIconBG
+                  : Theme.of(context)
+                      .extension<StackColors>()!
+                      .textFieldDefaultBG,
+              borderRadius: BorderRadius.circular(32),
             ),
-          );
-        },
-        child: Padding(
-          padding: const EdgeInsets.all(8.0),
-          child: Row(
-            children: [
-              Container(
-                width: 32,
-                height: 32,
-                decoration: BoxDecoration(
-                  color: contact.id == "default"
-                      ? Theme.of(context)
-                          .extension<StackColors>()!
-                          .myStackContactIconBG
-                      : Theme.of(context)
-                          .extension<StackColors>()!
-                          .textFieldDefaultBG,
-                  borderRadius: BorderRadius.circular(32),
-                ),
-                child: contact.id == "default"
+            child: contact.id == "default"
+                ? Center(
+                    child: SvgPicture.asset(
+                      Assets.svg.stackIcon(context),
+                      width: 20,
+                    ),
+                  )
+                : contact.emojiChar != null
                     ? Center(
-                        child: SvgPicture.asset(
-                          Assets.svg.stackIcon(context),
-                          width: 20,
-                        ),
+                        child: Text(contact.emojiChar!),
                       )
-                    : contact.emojiChar != null
-                        ? Center(
-                            child: Text(contact.emojiChar!),
-                          )
-                        : Center(
-                            child: SvgPicture.asset(
-                              Assets.svg.user,
-                              width: 18,
-                            ),
-                          ),
-              ),
-              const SizedBox(
-                width: 12,
-              ),
-              if (isDesktop)
+                    : Center(
+                        child: SvgPicture.asset(
+                          Assets.svg.user,
+                          width: 18,
+                        ),
+                      ),
+          ),
+          const SizedBox(
+            width: 12,
+          ),
+          if (isDesktop)
+            Text(
+              contact.name,
+              style: STextStyles.itemSubtitle12(context),
+            ),
+          if (isDesktop)
+            const SizedBox(
+              width: 16,
+            ),
+          if (isDesktop)
+            Text(
+              coinsString,
+              style: STextStyles.label(context),
+            ),
+          if (!isDesktop)
+            Column(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: [
                 Text(
                   contact.name,
                   style: STextStyles.itemSubtitle12(context),
                 ),
-              if (isDesktop)
                 const SizedBox(
-                  width: 16,
+                  height: 4,
                 ),
-              if (isDesktop)
                 Text(
                   coinsString,
                   style: STextStyles.label(context),
                 ),
-              if (!isDesktop)
-                Column(
-                  crossAxisAlignment: CrossAxisAlignment.start,
-                  children: [
-                    Text(
-                      contact.name,
-                      style: STextStyles.itemSubtitle12(context),
-                    ),
-                    const SizedBox(
-                      height: 4,
-                    ),
-                    Text(
-                      coinsString,
-                      style: STextStyles.label(context),
-                    ),
-                  ],
-                ),
-              if (isDesktop) const Spacer(),
-              // if (isDesktop)
-              //   SvgPicture.asset(
-              //     widget.indicatorDown == true
-              //         ? Assets.svg.chevronDown
-              //         : Assets.svg.chevronUp,
-              //     width: 10,
-              //     height: 5,
-              //     color:
-              //         Theme.of(context).extension<StackColors>()!.textSubtitle2,
-              //   ),
-            ],
+              ],
+            ),
+          if (isDesktop) const Spacer(),
+          if (isDesktop)
+            SvgPicture.asset(
+              widget.indicatorDown == ExpandableState.collapsed
+                  ? Assets.svg.chevronDown
+                  : Assets.svg.chevronUp,
+              width: 10,
+              height: 5,
+              color: Theme.of(context).extension<StackColors>()!.textSubtitle2,
+            ),
+        ],
+      ),
+      builder: (child) => RoundedWhiteContainer(
+        padding: const EdgeInsets.all(4),
+        child: RawMaterialButton(
+          // splashColor: Theme.of(context).extension<StackColors>()!.highlight,
+          padding: const EdgeInsets.all(0),
+          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(
+              Constants.size.circularBorderRadius,
+            ),
+          ),
+          onPressed: () {
+            showDialog<void>(
+              context: context,
+              useSafeArea: true,
+              barrierDismissible: true,
+              builder: (_) => ContactPopUp(
+                contactId: contact.id,
+              ),
+            );
+          },
+          child: Padding(
+            padding: const EdgeInsets.all(8.0),
+            child: child,
           ),
         ),
       ),

From b6e4357c3c63a6567fbdf2809ffb0b9c4b22b4a7 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 10:23:12 -0600
Subject: [PATCH 010/100] wallet overview syncing/loading balance text color
 fix for darkmode

---
 .../wallet_view/sub_widgets/desktop_wallet_summary.dart         | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart
index 7a9e93467..f4bfed976 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart
@@ -243,7 +243,7 @@ class _WDesktopWalletSummaryState extends State<DesktopWalletSummary> {
                               fontSize: 24,
                               color: Theme.of(context)
                                   .extension<StackColors>()!
-                                  .textFavoriteCard,
+                                  .textDark,
                             ),
                           ),
                           if (externalCalls)

From 81d5f757b3d039528f523df3af8b8d1cca21a81e Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 11:10:26 -0600
Subject: [PATCH 011/100] WIP: desktop contact details

---
 .../desktop_address_book.dart                 | 252 ++++++++----------
 .../desktop_address_book_scaffold.dart        | 111 ++++++++
 .../subwidgets/desktop_contact_details.dart   | 191 +++++++++++++
 lib/widgets/address_book_card.dart            |   9 +-
 4 files changed, 427 insertions(+), 136 deletions(-)
 create mode 100644 lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_book_scaffold.dart
 create mode 100644 lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart

diff --git a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
index 51b075284..5e22a6089 100644
--- a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
@@ -5,7 +5,11 @@ import 'package:stackwallet/models/contact.dart';
 import 'package:stackwallet/models/contact_address_entry.dart';
 import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart';
 import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart';
+import 'package:stackwallet/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_book_scaffold.dart';
+import 'package:stackwallet/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart';
 import 'package:stackwallet/providers/global/address_book_service_provider.dart';
+import 'package:stackwallet/providers/providers.dart';
+import 'package:stackwallet/providers/ui/address_book_providers/address_book_filter_provider.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
@@ -19,13 +23,11 @@ import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
+import 'package:stackwallet/widgets/rounded_container.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 import 'package:stackwallet/widgets/textfield_icon_button.dart';
 
-import '../../../providers/providers.dart';
-import '../../../providers/ui/address_book_providers/address_book_filter_provider.dart';
-
 class DesktopAddressBook extends ConsumerStatefulWidget {
   const DesktopAddressBook({Key? key}) : super(key: key);
 
@@ -42,6 +44,8 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
 
   String _searchTerm = "";
 
+  String? currentContactId;
+
   Future<void> selectCryptocurrency() async {
     await showDialog<dynamic>(
       context: context,
@@ -139,8 +143,9 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
             .where((e) => ref.watch(addressBookFilterProvider
                 .select((value) => value.coins.contains(e.coin))))
             .isNotEmpty)
-        .where((e) =>
-            ref.read(addressBookServiceProvider).matches(_searchTerm, e));
+        .where(
+            (e) => ref.read(addressBookServiceProvider).matches(_searchTerm, e))
+        .toList();
 
     final favorites = contacts
         .where((element) => element.addresses
@@ -150,7 +155,8 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
         .where((e) =>
             e.isFavorite &&
             ref.read(addressBookServiceProvider).matches(_searchTerm, e))
-        .where((element) => element.isFavorite);
+        .where((element) => element.isFavorite)
+        .toList();
 
     return DesktopScaffold(
       appBar: DesktopAppBar(
@@ -294,12 +300,56 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
                   padding: const EdgeInsets.all(0),
                   child: Column(
                     children: [
-                      ...favorites.map(
-                        (e) => AddressBookCard(
-                          key: Key("favContactCard_${e.id}_key"),
-                          contactId: e.id,
+                      for (int i = 0; i < favorites.length; i++)
+                        Column(
+                          children: [
+                            if (i > 0)
+                              Container(
+                                color: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .background,
+                                height: 1,
+                              ),
+                            Padding(
+                              padding: const EdgeInsets.all(4),
+                              child: RoundedContainer(
+                                padding: const EdgeInsets.all(0),
+                                color: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .accentColorDark
+                                    .withOpacity(
+                                      currentContactId == favorites[i].id
+                                          ? 0.08
+                                          : 0,
+                                    ),
+                                child: RawMaterialButton(
+                                  onPressed: () {
+                                    setState(() {
+                                      currentContactId = favorites[i].id;
+                                    });
+                                  },
+                                  padding: const EdgeInsets.symmetric(
+                                    horizontal: 20,
+                                    vertical: 16,
+                                  ),
+                                  materialTapTargetSize:
+                                      MaterialTapTargetSize.shrinkWrap,
+                                  shape: RoundedRectangleBorder(
+                                    borderRadius: BorderRadius.circular(
+                                      Constants.size.circularBorderRadius,
+                                    ),
+                                  ),
+                                  child: AddressBookCard(
+                                    key: Key(
+                                        "favContactCard_${favorites[i].id}_key"),
+                                    contactId: favorites[i].id,
+                                    desktopSendFrom: false,
+                                  ),
+                                ),
+                              ),
+                            ),
+                          ],
                         ),
-                      ),
                     ],
                   ),
                 ),
@@ -318,136 +368,70 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
                   children: [
                     RoundedWhiteContainer(
                       padding: const EdgeInsets.all(0),
-                      child: Padding(
-                        padding: const EdgeInsets.all(8.0),
-                        child: Column(
-                          children: [
-                            ...allContacts.map(
-                              (e) => AddressBookCard(
-                                key: Key("desktopContactCard_${e.id}_key"),
-                                contactId: e.id,
-                              ),
+                      child: Column(
+                        children: [
+                          for (int i = 0; i < allContacts.length; i++)
+                            Column(
+                              children: [
+                                if (i > 0)
+                                  Container(
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .background,
+                                    height: 1,
+                                  ),
+                                Padding(
+                                  padding: const EdgeInsets.all(4),
+                                  child: RoundedContainer(
+                                    padding: const EdgeInsets.all(0),
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .accentColorDark
+                                        .withOpacity(
+                                          currentContactId == allContacts[i].id
+                                              ? 0.08
+                                              : 0,
+                                        ),
+                                    child: RawMaterialButton(
+                                      onPressed: () {
+                                        setState(() {
+                                          currentContactId = allContacts[i].id;
+                                        });
+                                      },
+                                      padding: const EdgeInsets.symmetric(
+                                        horizontal: 20,
+                                        vertical: 16,
+                                      ),
+                                      materialTapTargetSize:
+                                          MaterialTapTargetSize.shrinkWrap,
+                                      shape: RoundedRectangleBorder(
+                                        borderRadius: BorderRadius.circular(
+                                          Constants.size.circularBorderRadius,
+                                        ),
+                                      ),
+                                      child: AddressBookCard(
+                                        key: Key(
+                                            "favContactCard_${allContacts[i].id}_key"),
+                                        contactId: allContacts[i].id,
+                                        desktopSendFrom: false,
+                                      ),
+                                    ),
+                                  ),
+                                ),
+                              ],
                             ),
-                          ],
-                        ),
+                        ],
                       ),
                     ),
                   ],
                 ),
-          details: Container(
-            color: Colors.purple,
-          ),
+          details: currentContactId == null
+              ? Container()
+              : DesktopContactDetails(
+                  contactId: currentContactId!,
+                ),
         ),
       ),
     );
   }
 }
-
-class DesktopAddressBookScaffold extends StatelessWidget {
-  const DesktopAddressBookScaffold({
-    Key? key,
-    required this.controlsLeft,
-    required this.controlsRight,
-    required this.filterItems,
-    required this.upperLabel,
-    required this.lowerLabel,
-    required this.favorites,
-    required this.all,
-    required this.details,
-  }) : super(key: key);
-
-  final Widget? controlsLeft;
-  final Widget? controlsRight;
-  final Widget? filterItems;
-  final Widget? upperLabel;
-  final Widget? lowerLabel;
-  final Widget? favorites;
-  final Widget? all;
-  final Widget? details;
-
-  static const double weirdRowHeight = 30;
-
-  @override
-  Widget build(BuildContext context) {
-    return Column(
-      children: [
-        Row(
-          mainAxisAlignment: MainAxisAlignment.end,
-          children: [
-            Expanded(
-              flex: 6,
-              child: controlsLeft ?? Container(),
-            ),
-            const SizedBox(
-              width: 20,
-            ),
-            Expanded(
-              flex: 5,
-              child: controlsRight ?? Container(),
-            ),
-          ],
-        ),
-        const SizedBox(
-          height: 20,
-        ),
-        Row(
-          children: [
-            Expanded(
-              child: filterItems ?? Container(),
-            ),
-          ],
-        ),
-        Expanded(
-          child: Row(
-            children: [
-              Expanded(
-                flex: 6,
-                child: LayoutBuilder(
-                  builder: (context, constraints) {
-                    return SingleChildScrollView(
-                      child: ConstrainedBox(
-                        constraints: BoxConstraints(
-                          minHeight: constraints.maxHeight,
-                        ),
-                        child: IntrinsicHeight(
-                          child: Column(
-                            crossAxisAlignment: CrossAxisAlignment.start,
-                            children: [
-                              SizedBox(
-                                height: weirdRowHeight,
-                                child: upperLabel,
-                              ),
-                              favorites ?? Container(),
-                              lowerLabel ?? Container(),
-                              all ?? Container(),
-                            ],
-                          ),
-                        ),
-                      ),
-                    );
-                  },
-                ),
-              ),
-              const SizedBox(
-                width: 20,
-              ),
-              Expanded(
-                flex: 5,
-                child: Column(
-                  children: [
-                    const SizedBox(
-                      height: weirdRowHeight,
-                    ),
-                    Expanded(
-                      child: details ?? Container(),
-                    ),
-                  ],
-                ),
-              ),
-            ],
-          ),
-        )
-      ],
-    );
-  }
-}
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_book_scaffold.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_book_scaffold.dart
new file mode 100644
index 000000000..f32ea1f7f
--- /dev/null
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_book_scaffold.dart
@@ -0,0 +1,111 @@
+import 'package:flutter/widgets.dart';
+
+class DesktopAddressBookScaffold extends StatelessWidget {
+  const DesktopAddressBookScaffold({
+    Key? key,
+    required this.controlsLeft,
+    required this.controlsRight,
+    required this.filterItems,
+    required this.upperLabel,
+    required this.lowerLabel,
+    required this.favorites,
+    required this.all,
+    required this.details,
+  }) : super(key: key);
+
+  final Widget? controlsLeft;
+  final Widget? controlsRight;
+  final Widget? filterItems;
+  final Widget? upperLabel;
+  final Widget? lowerLabel;
+  final Widget? favorites;
+  final Widget? all;
+  final Widget? details;
+
+  static const double weirdRowHeight = 30;
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        Row(
+          mainAxisAlignment: MainAxisAlignment.end,
+          children: [
+            Expanded(
+              flex: 6,
+              child: controlsLeft ?? Container(),
+            ),
+            const SizedBox(
+              width: 20,
+            ),
+            Expanded(
+              flex: 5,
+              child: controlsRight ?? Container(),
+            ),
+          ],
+        ),
+        const SizedBox(
+          height: 20,
+        ),
+        Row(
+          children: [
+            Expanded(
+              child: filterItems ?? Container(),
+            ),
+          ],
+        ),
+        Expanded(
+          child: Row(
+            children: [
+              Expanded(
+                flex: 6,
+                child: LayoutBuilder(
+                  builder: (context, constraints) {
+                    return SingleChildScrollView(
+                      primary: false,
+                      child: ConstrainedBox(
+                        constraints: BoxConstraints(
+                          minHeight: constraints.maxHeight,
+                        ),
+                        child: IntrinsicHeight(
+                          child: Column(
+                            crossAxisAlignment: CrossAxisAlignment.start,
+                            children: [
+                              SizedBox(
+                                height: weirdRowHeight,
+                                child: upperLabel,
+                              ),
+                              favorites ?? Container(),
+                              lowerLabel ?? Container(),
+                              all ?? Container(),
+                            ],
+                          ),
+                        ),
+                      ),
+                    );
+                  },
+                ),
+              ),
+              const SizedBox(
+                width: 20,
+              ),
+              Expanded(
+                flex: 5,
+                child: Column(
+                  children: [
+                    const SizedBox(
+                      height: weirdRowHeight,
+                    ),
+                    Expanded(
+                      child: details ?? Container(),
+                    ),
+                  ],
+                ),
+              ),
+            ],
+          ),
+        )
+      ],
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
new file mode 100644
index 000000000..5184b2293
--- /dev/null
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
@@ -0,0 +1,191 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:stackwallet/models/contact_address_entry.dart';
+import 'package:stackwallet/providers/global/address_book_service_provider.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/enums/coin_enum.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+
+class DesktopContactDetails extends ConsumerStatefulWidget {
+  const DesktopContactDetails({
+    Key? key,
+    required this.contactId,
+  }) : super(key: key);
+
+  final String contactId;
+
+  @override
+  ConsumerState<DesktopContactDetails> createState() =>
+      _DesktopContactDetailsState();
+}
+
+class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
+  @override
+  Widget build(BuildContext context) {
+    final contact = ref.watch(addressBookServiceProvider
+        .select((value) => value.getContactById(widget.contactId)));
+
+    return Column(
+      children: [
+        Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            Row(
+              children: [
+                Container(
+                  width: 32,
+                  height: 32,
+                  decoration: BoxDecoration(
+                    color: Theme.of(context)
+                        .extension<StackColors>()!
+                        .textFieldDefaultBG,
+                    borderRadius: BorderRadius.circular(32),
+                  ),
+                  child: contact.id == "default"
+                      ? Center(
+                          child: SvgPicture.asset(
+                            Assets.svg.stackIcon(context),
+                            width: 20,
+                          ),
+                        )
+                      : contact.emojiChar != null
+                          ? Center(
+                              child: Text(contact.emojiChar!),
+                            )
+                          : Center(
+                              child: SvgPicture.asset(
+                                Assets.svg.user,
+                                width: 18,
+                              ),
+                            ),
+                ),
+                const SizedBox(
+                  width: 16,
+                ),
+                Text(
+                  contact.name,
+                  style: STextStyles.desktopTextSmall(context),
+                ),
+              ],
+            ),
+            SecondaryButton(
+              label: "Options",
+              onPressed: () {},
+            ),
+          ],
+        ),
+        const SizedBox(
+          height: 24,
+        ),
+        Expanded(
+          child: LayoutBuilder(
+            builder: (context, constraints) {
+              return SingleChildScrollView(
+                child: ConstrainedBox(
+                  constraints: BoxConstraints(
+                    minHeight: constraints.maxHeight,
+                  ),
+                  child: IntrinsicHeight(
+                    child: Column(
+                      children: [
+                        Row(
+                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                          children: [
+                            Text(
+                              "Addresses",
+                              style: STextStyles.desktopTextExtraExtraSmall(
+                                  context),
+                            ),
+                            BlueTextButton(
+                              text: "Add new",
+                              onTap: () {},
+                            ),
+                          ],
+                        ),
+                        Column(
+                          mainAxisSize: MainAxisSize.min,
+                          children: [
+                            ...contact.addresses
+                                .map((e) => AddressCard(entry: e)),
+                          ],
+                        )
+                      ],
+                    ),
+                  ),
+                ),
+              );
+            },
+          ),
+        ),
+      ],
+    );
+  }
+}
+
+class AddressCard extends StatelessWidget {
+  const AddressCard({
+    Key? key,
+    required this.entry,
+  }) : super(key: key);
+
+  final ContactAddressEntry entry;
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      children: [
+        SvgPicture.asset(
+          Assets.svg.iconFor(
+            coin: entry.coin,
+          ),
+          height: 32,
+          width: 32,
+        ),
+        const SizedBox(
+          width: 16,
+        ),
+        Column(
+          mainAxisSize: MainAxisSize.min,
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            SelectableText(
+              "${entry.label} ${entry.coin.ticker}",
+              style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+                color: Theme.of(context).extension<StackColors>()!.textDark,
+              ),
+            ),
+            const SizedBox(
+              height: 2,
+            ),
+            SelectableText(
+              entry.address,
+              style: STextStyles.desktopTextExtraExtraSmall(context),
+            ),
+            const SizedBox(
+              height: 8,
+            ),
+            Row(
+              children: [
+                BlueTextButton(
+                  text: "Copy",
+                  onTap: () {},
+                ),
+                const SizedBox(
+                  width: 16,
+                ),
+                BlueTextButton(
+                  text: "Edit",
+                  onTap: () {},
+                ),
+              ],
+            )
+          ],
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/widgets/address_book_card.dart b/lib/widgets/address_book_card.dart
index 329e35fdf..b79f89662 100644
--- a/lib/widgets/address_book_card.dart
+++ b/lib/widgets/address_book_card.dart
@@ -18,10 +18,12 @@ class AddressBookCard extends ConsumerStatefulWidget {
     Key? key,
     required this.contactId,
     this.indicatorDown,
+    this.desktopSendFrom = true,
   }) : super(key: key);
 
   final String contactId;
   final ExpandableState? indicatorDown;
+  final bool desktopSendFrom;
 
   @override
   ConsumerState<AddressBookCard> createState() => _AddressBookCardState();
@@ -30,10 +32,12 @@ class AddressBookCard extends ConsumerStatefulWidget {
 class _AddressBookCardState extends ConsumerState<AddressBookCard> {
   late final String contactId;
   late final bool isDesktop;
+  late final bool desktopSendFrom;
 
   @override
   void initState() {
     contactId = widget.contactId;
+    desktopSendFrom = widget.desktopSendFrom;
     isDesktop = Util.isDesktop;
     super.initState();
   }
@@ -107,6 +111,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
             const SizedBox(
               width: 16,
             ),
+          if (isDesktop && !desktopSendFrom) const Spacer(),
           if (isDesktop)
             Text(
               coinsString,
@@ -129,8 +134,8 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
                 ),
               ],
             ),
-          if (isDesktop) const Spacer(),
-          if (isDesktop)
+          if (isDesktop && desktopSendFrom) const Spacer(),
+          if (isDesktop && desktopSendFrom)
             SvgPicture.asset(
               widget.indicatorDown == ExpandableState.collapsed
                   ? Assets.svg.chevronDown

From 9063749eadcaf1ab414b37db7591d55049efcfe3 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Thu, 17 Nov 2022 10:42:11 -0700
Subject: [PATCH 012/100] anonymize button added to firo wallet

---
 .../wallet_view/desktop_wallet_view.dart      | 135 ++++++++++++++++++
 1 file changed, 135 insertions(+)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
index 81b531632..769f22157 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
@@ -1,5 +1,6 @@
 import 'dart:async';
 
+import 'package:decimal/decimal.dart';
 import 'package:event_bus/event_bus.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -15,6 +16,7 @@ import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_vie
 import 'package:stackwallet/providers/global/auto_swb_service_provider.dart';
 import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
+import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
 import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
 import 'package:stackwallet/services/event_bus/global_event_bus.dart';
 import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
@@ -27,8 +29,11 @@ import 'package:stackwallet/utilities/logger.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+import 'package:stackwallet/widgets/custom_loading_overlay.dart';
 import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/hover_text_field.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
@@ -165,6 +170,75 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
     }
   }
 
+  Future<void> attemptAnonymize() async {
+    final managerProvider =
+        ref.read(walletsChangeNotifierProvider).getManagerProvider(walletId);
+
+    bool shouldPop = false;
+    unawaited(
+      showDialog(
+        context: context,
+        builder: (context) => WillPopScope(
+          child: const CustomLoadingOverlay(
+            message: "Anonymizing balance",
+            eventBus: null,
+          ),
+          onWillPop: () async => shouldPop,
+        ),
+      ),
+    );
+    final firoWallet = ref.read(managerProvider).wallet as FiroWallet;
+
+    final publicBalance = await firoWallet.availablePublicBalance();
+    if (publicBalance <= Decimal.zero) {
+      shouldPop = true;
+      if (mounted) {
+        Navigator.of(context).popUntil(
+          ModalRoute.withName(DesktopWalletView.routeName),
+        );
+        unawaited(
+          showFloatingFlushBar(
+            type: FlushBarType.info,
+            message: "No funds available to anonymize!",
+            context: context,
+          ),
+        );
+      }
+      return;
+    }
+
+    try {
+      await firoWallet.anonymizeAllPublicFunds();
+      shouldPop = true;
+      if (mounted) {
+        Navigator.of(context).popUntil(
+          ModalRoute.withName(DesktopWalletView.routeName),
+        );
+        unawaited(
+          showFloatingFlushBar(
+            type: FlushBarType.success,
+            message: "Anonymize transaction submitted",
+            context: context,
+          ),
+        );
+      }
+    } catch (e) {
+      shouldPop = true;
+      if (mounted) {
+        Navigator.of(context).popUntil(
+          ModalRoute.withName(DesktopWalletView.routeName),
+        );
+        await showDialog<dynamic>(
+          context: context,
+          builder: (_) => StackOkDialog(
+            title: "Anonymize all failed",
+            message: "Reason: $e",
+          ),
+        );
+      }
+    }
+  }
+
   @override
   void initState() {
     controller = TextEditingController();
@@ -333,6 +407,67 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
                         : WalletSyncStatus.synced,
                   ),
                   const Spacer(),
+                  if (coin == Coin.firo) const SizedBox(width: 10),
+                  if (coin == Coin.firo)
+                    SecondaryButton(
+                      width: 180,
+                      desktopMed: true,
+                      label: "Anonymize funds",
+                      onPressed: () async {
+                        await showDialog<void>(
+                          context: context,
+                          barrierDismissible: false,
+                          builder: (context) => DesktopDialog(
+                            maxWidth: 500,
+                            maxHeight: 210,
+                            child: Padding(
+                              padding: const EdgeInsets.symmetric(
+                                  horizontal: 32, vertical: 20),
+                              child: Column(
+                                children: [
+                                  Text(
+                                    "Attention!",
+                                    style: STextStyles.desktopH2(context),
+                                  ),
+                                  const SizedBox(height: 16),
+                                  Text(
+                                    "You're about to anonymize all of your public funds.",
+                                    style:
+                                        STextStyles.desktopTextSmall(context),
+                                  ),
+                                  const SizedBox(height: 32),
+                                  Row(
+                                    mainAxisAlignment: MainAxisAlignment.center,
+                                    children: [
+                                      SecondaryButton(
+                                        width: 180,
+                                        desktopMed: true,
+                                        label: "Cancel",
+                                        onPressed: () {
+                                          Navigator.of(context).pop();
+                                        },
+                                      ),
+                                      const SizedBox(width: 20),
+                                      PrimaryButton(
+                                        width: 180,
+                                        desktopMed: true,
+                                        label: "Continue",
+                                        onPressed: () {
+                                          Navigator.of(context).pop();
+
+                                          unawaited(attemptAnonymize());
+                                        },
+                                      )
+                                    ],
+                                  ),
+                                ],
+                              ),
+                            ),
+                          ),
+                        );
+                      },
+                    ),
+                  if (coin == Coin.firo) const SizedBox(width: 16),
                   SecondaryButton(
                     width: 180,
                     desktopMed: true,

From 9e7c1ccf9dc20e08ac74120e7faf866e1db3f103 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 11:46:44 -0600
Subject: [PATCH 013/100] button size enum

---
 .../subviews/address_book_filter_view.dart    |  4 +-
 .../generate_receiving_uri_qr_code_view.dart  |  5 +-
 .../send_view/confirm_transaction_view.dart   |  4 +-
 .../building_transaction_dialog.dart          |  2 +-
 .../global_settings_view/currency_view.dart   |  4 +-
 .../add_edit_node_view.dart                   |  8 +-
 .../manage_nodes_views/node_details_view.dart |  4 +-
 .../create_backup_view.dart                   |  8 +-
 .../dialogs/cancel_stack_restore_dialog.dart  |  4 +-
 .../edit_auto_backup_view.dart                |  4 +-
 .../restore_from_file_view.dart               |  4 +-
 .../stack_restore_progress_view.dart          |  8 +-
 .../sub_widgets/confirm_full_rescan.dart      |  4 +-
 .../all_transactions_view.dart                |  2 +-
 .../transaction_search_filter_view.dart       |  4 +-
 .../desktop_address_book.dart                 |  4 +-
 .../wallet_view/desktop_wallet_view.dart      |  2 +-
 .../sub_widgets/desktop_auth_send.dart        |  4 +-
 .../sub_widgets/desktop_receive.dart          |  2 +-
 .../wallet_view/sub_widgets/desktop_send.dart | 10 +--
 .../backup_and_restore_settings.dart          | 14 +--
 .../create_auto_backup.dart                   |  7 +-
 .../enable_backup_dialog.dart                 |  4 +-
 .../currency_settings/currency_settings.dart  |  2 +-
 .../language_settings/language_settings.dart  |  2 +-
 .../home/settings_menu/security_settings.dart |  4 +-
 .../syncing_preferences_settings.dart         |  2 +-
 lib/widgets/desktop/custom_text_button.dart   | 10 +++
 lib/widgets/desktop/primary_button.dart       | 86 +++++++++++++++---
 lib/widgets/desktop/secondary_button.dart     | 89 ++++++++++++++++---
 30 files changed, 225 insertions(+), 86 deletions(-)

diff --git a/lib/pages/address_book_views/subviews/address_book_filter_view.dart b/lib/pages/address_book_views/subviews/address_book_filter_view.dart
index df779331e..c129251d5 100644
--- a/lib/pages/address_book_views/subviews/address_book_filter_view.dart
+++ b/lib/pages/address_book_views/subviews/address_book_filter_view.dart
@@ -159,7 +159,7 @@ class _AddressBookFilterViewState extends ConsumerState<AddressBookFilterView> {
                   children: [
                     SecondaryButton(
                       width: 248,
-                      desktopMed: true,
+                      buttonHeight: ButtonHeight.l,
                       enabled: true,
                       label: "Cancel",
                       onPressed: () {
@@ -169,7 +169,7 @@ class _AddressBookFilterViewState extends ConsumerState<AddressBookFilterView> {
                     // const SizedBox(width: 16),
                     PrimaryButton(
                       width: 248,
-                      desktopMed: true,
+                      buttonHeight: ButtonHeight.l,
                       enabled: true,
                       label: "Apply",
                       onPressed: () {
diff --git a/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart b/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart
index 981def830..05cedb148 100644
--- a/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart
+++ b/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart
@@ -530,7 +530,7 @@ class _GenerateUriQrCodeViewState extends State<GenerateUriQrCodeView> {
                       });
                     }
                   : onGeneratePressed,
-              desktopMed: true,
+              buttonHeight: ButtonHeight.l,
             ),
             if (isDesktop && didGenerate)
               Row(
@@ -586,7 +586,6 @@ class _GenerateUriQrCodeViewState extends State<GenerateUriQrCodeView> {
                                 if (!isDesktop)
                                   SecondaryButton(
                                     width: 170,
-                                    desktopMed: true,
                                     onPressed: () async {
                                       await _capturePng(false);
                                     },
@@ -606,7 +605,7 @@ class _GenerateUriQrCodeViewState extends State<GenerateUriQrCodeView> {
                                   ),
                                 PrimaryButton(
                                   width: 170,
-                                  desktopMed: true,
+                                  buttonHeight: ButtonHeight.l,
                                   onPressed: () async {
                                     // TODO: add save functionality instead of share
                                     // save works on linux at the moment
diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart
index 0f1692c08..8f7afb0bb 100644
--- a/lib/pages/send_view/confirm_transaction_view.dart
+++ b/lib/pages/send_view/confirm_transaction_view.dart
@@ -148,7 +148,7 @@ class _ConfirmTransactionViewState
                         const Spacer(),
                         Expanded(
                           child: PrimaryButton(
-                            desktopMed: true,
+                            buttonHeight: ButtonHeight.l,
                             label: "Ok",
                             onPressed: Navigator.of(context).pop,
                           ),
@@ -780,7 +780,7 @@ class _ConfirmTransactionViewState
                   : const EdgeInsets.all(0),
               child: PrimaryButton(
                 label: "Send",
-                desktopMed: true,
+                buttonHeight: ButtonHeight.l,
                 onPressed: () async {
                   final dynamic unlocked;
 
diff --git a/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart b/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart
index 045218e54..1f6c95df6 100644
--- a/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart
+++ b/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart
@@ -77,7 +77,7 @@ class _RestoringDialogState extends State<BuildingTransactionDialog>
             height: 40,
           ),
           SecondaryButton(
-            desktopMed: true,
+            buttonHeight: ButtonHeight.l,
             label: "Cancel",
             onPressed: () {
               onCancel.call();
diff --git a/lib/pages/settings_views/global_settings_view/currency_view.dart b/lib/pages/settings_views/global_settings_view/currency_view.dart
index 4e8fd5f6e..dccf2d61b 100644
--- a/lib/pages/settings_views/global_settings_view/currency_view.dart
+++ b/lib/pages/settings_views/global_settings_view/currency_view.dart
@@ -189,7 +189,7 @@ class _CurrencyViewState extends ConsumerState<BaseCurrencySettingsView> {
                     Expanded(
                       child: SecondaryButton(
                         label: "Cancel",
-                        desktopMed: true,
+                        buttonHeight: ButtonHeight.l,
                         onPressed: Navigator.of(context).pop,
                       ),
                     ),
@@ -199,7 +199,7 @@ class _CurrencyViewState extends ConsumerState<BaseCurrencySettingsView> {
                     Expanded(
                       child: PrimaryButton(
                         label: "Save changes",
-                        desktopMed: true,
+                        buttonHeight: ButtonHeight.l,
                         onPressed: () {
                           ref.read(prefsChangeNotifierProvider).currency =
                               current;
diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
index 890953caf..606c4481f 100644
--- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
+++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
@@ -238,7 +238,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
                                 Expanded(
                                   child: SecondaryButton(
                                     label: "Cancel",
-                                    desktopMed: true,
+                                    buttonHeight: ButtonHeight.l,
                                     onPressed: () => Navigator.of(
                                       context,
                                       rootNavigator: true,
@@ -251,7 +251,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
                                 Expanded(
                                   child: PrimaryButton(
                                     label: "Save",
-                                    desktopMed: true,
+                                    buttonHeight: ButtonHeight.l,
                                     onPressed: () => Navigator.of(
                                       context,
                                       rootNavigator: true,
@@ -561,7 +561,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
                   child: SecondaryButton(
                     label: "Test connection",
                     enabled: testConnectionEnabled,
-                    desktopMed: true,
+                    buttonHeight: ButtonHeight.l,
                     onPressed: testConnectionEnabled
                         ? () async {
                             await _testConnection();
@@ -578,7 +578,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
                     child: PrimaryButton(
                       label: "Save",
                       enabled: saveEnabled,
-                      desktopMed: true,
+                      buttonHeight: ButtonHeight.l,
                       onPressed: saveEnabled ? attemptSave : null,
                     ),
                   ),
diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart
index a80a64147..3d49ae6f7 100644
--- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart
+++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart
@@ -349,7 +349,7 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
                 Expanded(
                   child: SecondaryButton(
                     label: "Test connection",
-                    desktopMed: true,
+                    buttonHeight: ButtonHeight.l,
                     onPressed: () async {
                       await _testConnection(ref, context);
                     },
@@ -364,7 +364,7 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
                     child: !nodeId.startsWith("default")
                         ? PrimaryButton(
                             label: _desktopReadOnly ? "Edit" : "Save",
-                            desktopMed: true,
+                            buttonHeight: ButtonHeight.l,
                             onPressed: () async {
                               final shouldSave = _desktopReadOnly == false;
                               setState(() {
diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart
index 02556beb9..0609e4b1b 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart
@@ -562,7 +562,7 @@ class _RestoreFromFileViewState extends State<CreateBackupView> {
                       Consumer(builder: (context, ref, __) {
                         return PrimaryButton(
                           width: 183,
-                          desktopMed: true,
+                          buttonHeight: ButtonHeight.l,
                           label: "Create backup",
                           enabled: shouldEnableCreate,
                           onPressed: !shouldEnableCreate
@@ -735,7 +735,9 @@ class _RestoreFromFileViewState extends State<CreateBackupView> {
                                                             child:
                                                                 PrimaryButton(
                                                               label: "Ok",
-                                                              desktopMed: true,
+                                                              buttonHeight:
+                                                                  ButtonHeight
+                                                                      .l,
                                                               onPressed: () {
                                                                 int count = 0;
                                                                 Navigator.of(
@@ -778,7 +780,7 @@ class _RestoreFromFileViewState extends State<CreateBackupView> {
                       ),
                       SecondaryButton(
                         width: 183,
-                        desktopMed: true,
+                        buttonHeight: ButtonHeight.l,
                         label: "Cancel",
                         onPressed: () {},
                       ),
diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/dialogs/cancel_stack_restore_dialog.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/dialogs/cancel_stack_restore_dialog.dart
index a9f4e134d..905cdea72 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/dialogs/cancel_stack_restore_dialog.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/dialogs/cancel_stack_restore_dialog.dart
@@ -85,7 +85,7 @@ class CancelStackRestoreDialog extends StatelessWidget {
                       children: [
                         SecondaryButton(
                           width: 248,
-                          desktopMed: true,
+                          buttonHeight: ButtonHeight.l,
                           enabled: true,
                           label: "Keep restoring",
                           onPressed: () {
@@ -95,7 +95,7 @@ class CancelStackRestoreDialog extends StatelessWidget {
                         const SizedBox(width: 20),
                         PrimaryButton(
                           width: 248,
-                          desktopMed: true,
+                          buttonHeight: ButtonHeight.l,
                           enabled: true,
                           label: "Cancel anyway",
                           onPressed: () {
diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart
index 76d280980..310be9f2b 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart
@@ -754,7 +754,7 @@ class _EditAutoBackupViewState extends ConsumerState<EditAutoBackupView> {
                 Expanded(
                   child: SecondaryButton(
                     label: "Cancel",
-                    desktopMed: true,
+                    buttonHeight: ButtonHeight.l,
                     onPressed: Navigator.of(context).pop,
                   ),
                 ),
@@ -764,7 +764,7 @@ class _EditAutoBackupViewState extends ConsumerState<EditAutoBackupView> {
                 Expanded(
                   child: PrimaryButton(
                     label: "Save",
-                    desktopMed: true,
+                    buttonHeight: ButtonHeight.l,
                     enabled: shouldEnableCreate,
                     onPressed: onSavePressed,
                   ),
diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart
index c5ccfa6b3..9be6af4cb 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart
@@ -389,7 +389,7 @@ class _RestoreFromFileViewState extends ConsumerState<RestoreFromFileView> {
                       children: [
                         PrimaryButton(
                           width: 183,
-                          desktopMed: true,
+                          buttonHeight: ButtonHeight.l,
                           label: "Restore",
                           enabled: !(passwordController.text.isEmpty ||
                               fileLocationController.text.isEmpty),
@@ -566,7 +566,7 @@ class _RestoreFromFileViewState extends ConsumerState<RestoreFromFileView> {
                         ),
                         SecondaryButton(
                           width: 183,
-                          desktopMed: true,
+                          buttonHeight: ButtonHeight.l,
                           label: "Cancel",
                           onPressed: () {},
                         ),
diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart
index e34def23d..c7f53378d 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart
@@ -108,7 +108,7 @@ class _StackRestoreProgressViewState
     //     children: [
     //       SecondaryButton(
     //         width: 248,
-    //         desktopMed: true,
+    //          buttonHeight: ButtonHeight.l,
     //         enabled: true,
     //         label: "Keep restoring",
     //         onPressed: () {
@@ -118,7 +118,7 @@ class _StackRestoreProgressViewState
     //       const SizedBox(width: 16),
     //       PrimaryButton(
     //         width: 248,
-    //         desktopMed: true,
+    //          buttonHeight: ButtonHeight.l,
     //         enabled: true,
     //         label: "Cancel anyway",
     //         onPressed: () {
@@ -681,7 +681,7 @@ class _StackRestoreProgressViewState
                           _success
                               ? PrimaryButton(
                                   width: 248,
-                                  desktopMed: true,
+                                  buttonHeight: ButtonHeight.l,
                                   enabled: true,
                                   label: "Done",
                                   onPressed: () async {
@@ -690,7 +690,7 @@ class _StackRestoreProgressViewState
                                 )
                               : SecondaryButton(
                                   width: 248,
-                                  desktopMed: true,
+                                  buttonHeight: ButtonHeight.l,
                                   enabled: true,
                                   label: "Cancel restore process",
                                   onPressed: () async {
diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/confirm_full_rescan.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/confirm_full_rescan.dart
index 950d8d79e..150af6ac5 100644
--- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/confirm_full_rescan.dart
+++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/confirm_full_rescan.dart
@@ -58,7 +58,7 @@ class ConfirmFullRescanDialog extends StatelessWidget {
                     children: [
                       Expanded(
                         child: SecondaryButton(
-                          desktopMed: true,
+                          buttonHeight: ButtonHeight.l,
                           onPressed: Navigator.of(context).pop,
                           label: "Cancel",
                         ),
@@ -68,7 +68,7 @@ class ConfirmFullRescanDialog extends StatelessWidget {
                       ),
                       Expanded(
                         child: PrimaryButton(
-                          desktopMed: true,
+                          buttonHeight: ButtonHeight.l,
                           onPressed: () {
                             Navigator.of(context).pop();
                             onConfirm.call();
diff --git a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart
index d41877a9a..95dcc8126 100644
--- a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart
+++ b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart
@@ -385,7 +385,7 @@ class _TransactionDetailsViewState extends ConsumerState<AllTransactionsView> {
                     ),
                   if (isDesktop)
                     SecondaryButton(
-                      desktopMed: isDesktop,
+                      buttonHeight: ButtonHeight.l,
                       width: 200,
                       label: "Filter",
                       icon: SvgPicture.asset(
diff --git a/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart b/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart
index abebb71e4..d135ea276 100644
--- a/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart
+++ b/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart
@@ -869,7 +869,7 @@ class _TransactionSearchViewState
             Expanded(
               child: SecondaryButton(
                 label: "Cancel",
-                desktopMed: isDesktop,
+                buttonHeight: ButtonHeight.l,
                 onPressed: () async {
                   if (!isDesktop) {
                     if (FocusScope.of(context).hasFocus) {
@@ -919,7 +919,7 @@ class _TransactionSearchViewState
             ),
             Expanded(
               child: PrimaryButton(
-                desktopMed: isDesktop,
+                buttonHeight: ButtonHeight.l,
                 onPressed: () async {
                   await _onApplyPressed();
                 },
diff --git a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
index 5e22a6089..f028a3424 100644
--- a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
@@ -240,7 +240,7 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
               SecondaryButton(
                 width: 184,
                 label: "Filter",
-                desktopMed: true,
+                buttonHeight: ButtonHeight.l,
                 icon: SvgPicture.asset(
                   Assets.svg.filter,
                   color: Theme.of(context)
@@ -255,7 +255,7 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
               PrimaryButton(
                 width: 184,
                 label: "Add new",
-                desktopMed: true,
+                buttonHeight: ButtonHeight.l,
                 icon: SvgPicture.asset(
                   Assets.svg.circlePlus,
                   color: Theme.of(context)
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
index 769f22157..952194244 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
@@ -470,7 +470,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
                   if (coin == Coin.firo) const SizedBox(width: 16),
                   SecondaryButton(
                     width: 180,
-                    desktopMed: true,
+                    buttonHeight: ButtonHeight.l,
                     onPressed: () {
                       _onExchangePressed(context);
                     },
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart
index 566a82b35..9f863c8a4 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart
@@ -142,7 +142,7 @@ class _DesktopAuthSendState extends ConsumerState<DesktopAuthSend> {
             Expanded(
               child: SecondaryButton(
                 label: "Cancel",
-                desktopMed: true,
+                buttonHeight: ButtonHeight.l,
                 onPressed: Navigator.of(context).pop,
               ),
             ),
@@ -153,7 +153,7 @@ class _DesktopAuthSendState extends ConsumerState<DesktopAuthSend> {
               child: PrimaryButton(
                 enabled: _confirmEnabled,
                 label: "Confirm",
-                desktopMed: true,
+                buttonHeight: ButtonHeight.l,
                 onPressed: () async {
                   // TODO show spinner while verifying passphrase
 
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart
index 9a59c3ec1..3de4ed1e3 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart
@@ -199,7 +199,7 @@ class _DesktopReceiveState extends ConsumerState<DesktopReceive> {
           ),
         if (coin != Coin.epicCash)
           SecondaryButton(
-            desktopMed: true,
+            buttonHeight: ButtonHeight.l,
             onPressed: generateNewAddress,
             label: "Generate new address",
           ),
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_send.dart
index af2c2517a..336dd7b4e 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_send.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_send.dart
@@ -145,7 +145,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
                       right: 32,
                     ),
                     child: SecondaryButton(
-                      desktopMed: true,
+                      buttonHeight: ButtonHeight.l,
                       label: "Ok",
                       onPressed: () {
                         Navigator.of(context).pop();
@@ -232,7 +232,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
                       children: [
                         Expanded(
                           child: SecondaryButton(
-                            desktopMed: true,
+                            buttonHeight: ButtonHeight.l,
                             label: "Cancel",
                             onPressed: () {
                               Navigator.of(context).pop(false);
@@ -244,7 +244,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
                         ),
                         Expanded(
                           child: PrimaryButton(
-                            desktopMed: true,
+                            buttonHeight: ButtonHeight.l,
                             label: "Yes",
                             onPressed: () {
                               Navigator.of(context).pop(true);
@@ -399,7 +399,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
                         ),
                         child: Expanded(
                           child: SecondaryButton(
-                            desktopMed: true,
+                            buttonHeight: ButtonHeight.l,
                             label: "Yes",
                             onPressed: () {
                               Navigator.of(
@@ -1385,7 +1385,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
           height: 36,
         ),
         PrimaryButton(
-          desktopMed: true,
+          buttonHeight: ButtonHeight.l,
           label: "Preview send",
           enabled: ref.watch(previewTxButtonStateProvider.state).state,
           onPressed: ref.watch(previewTxButtonStateProvider.state).state
diff --git a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/backup_and_restore_settings.dart b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/backup_and_restore_settings.dart
index 7d70d4d0f..37f3f35a6 100644
--- a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/backup_and_restore_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/backup_and_restore_settings.dart
@@ -240,7 +240,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                             children: [
                               Expanded(
                                 child: SecondaryButton(
-                                  desktopMed: true,
+                                  buttonHeight: ButtonHeight.l,
                                   label: "Cancel",
                                   onPressed: Navigator.of(context).pop,
                                 ),
@@ -248,7 +248,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                               const SizedBox(width: 16),
                               Expanded(
                                 child: PrimaryButton(
-                                  desktopMed: true,
+                                  buttonHeight: ButtonHeight.l,
                                   label: "Disable",
                                   onPressed: () {
                                     ref
@@ -422,7 +422,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                                 padding: const EdgeInsets.all(10),
                                 child: !isEnabledAutoBackup
                                     ? PrimaryButton(
-                                        desktopMed: true,
+                                        buttonHeight: ButtonHeight.l,
                                         width: 200,
                                         label: "Enable auto backup",
                                         onPressed: () {
@@ -467,7 +467,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                                           Row(
                                             children: [
                                               PrimaryButton(
-                                                desktopMed: true,
+                                                buttonHeight: ButtonHeight.l,
                                                 width: 190,
                                                 label: "Disable auto backup",
                                                 onPressed: () {
@@ -476,7 +476,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                                               ),
                                               const SizedBox(width: 16),
                                               SecondaryButton(
-                                                desktopMed: true,
+                                                buttonHeight: ButtonHeight.l,
                                                 width: 190,
                                                 label: "Edit auto backup",
                                                 onPressed: () {
@@ -560,7 +560,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                                         child: CreateBackupView(),
                                       )
                                     : PrimaryButton(
-                                        desktopMed: true,
+                                        buttonHeight: ButtonHeight.l,
                                         width: 200,
                                         label: "Create manual backup",
                                         onPressed: () {
@@ -642,7 +642,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                                         child: RestoreFromFileView(),
                                       )
                                     : PrimaryButton(
-                                        desktopMed: true,
+                                        buttonHeight: ButtonHeight.l,
                                         width: 200,
                                         label: "Restore backup",
                                         onPressed: () {
diff --git a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/create_auto_backup.dart b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/create_auto_backup.dart
index 663136dba..df80da732 100644
--- a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/create_auto_backup.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/create_auto_backup.dart
@@ -556,7 +556,7 @@ class _CreateAutoBackup extends ConsumerState<CreateAutoBackup> {
                 Expanded(
                   child: SecondaryButton(
                     label: "Cancel",
-                    desktopMed: true,
+                    buttonHeight: ButtonHeight.l,
                     onPressed: Navigator.of(context).pop,
                   ),
                 ),
@@ -565,7 +565,7 @@ class _CreateAutoBackup extends ConsumerState<CreateAutoBackup> {
                 ),
                 Expanded(
                   child: PrimaryButton(
-                    desktopMed: true,
+                    buttonHeight: ButtonHeight.l,
                     label: "Enable Auto Backup",
                     enabled: shouldEnableCreate,
                     onPressed: !shouldEnableCreate
@@ -792,7 +792,8 @@ class _CreateAutoBackup extends ConsumerState<CreateAutoBackup> {
                                                   Expanded(
                                                     child: PrimaryButton(
                                                       label: "Ok",
-                                                      desktopMed: true,
+                                                      buttonHeight:
+                                                          ButtonHeight.l,
                                                       onPressed: () {
                                                         Navigator.of(context)
                                                             .pop();
diff --git a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/enable_backup_dialog.dart b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/enable_backup_dialog.dart
index 6496253d5..df9f18b52 100644
--- a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/enable_backup_dialog.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/enable_backup_dialog.dart
@@ -59,7 +59,7 @@ class EnableBackupDialog extends StatelessWidget {
               children: [
                 Expanded(
                   child: SecondaryButton(
-                    desktopMed: true,
+                    buttonHeight: ButtonHeight.l,
                     label: "Cancel",
                     onPressed: () {
                       Navigator.of(context).pop();
@@ -71,7 +71,7 @@ class EnableBackupDialog extends StatelessWidget {
                 ),
                 Expanded(
                   child: PrimaryButton(
-                    desktopMed: true,
+                    buttonHeight: ButtonHeight.l,
                     label: "Continue",
                     onPressed: () {
                       Navigator.of(context).pop();
diff --git a/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart b/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart
index 4c4225ce4..0740157ad 100644
--- a/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart
@@ -108,7 +108,7 @@ class _CurrencySettings extends ConsumerState<CurrencySettings> {
                       ),
                       child: PrimaryButton(
                         width: 210,
-                        desktopMed: true,
+                        buttonHeight: ButtonHeight.l,
                         enabled: true,
                         label: "Change currency",
                         onPressed: () {
diff --git a/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart b/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart
index 08aeb9bc3..db636ba17 100644
--- a/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart
@@ -85,7 +85,7 @@ class _LanguageOptionSettings extends ConsumerState<LanguageOptionSettings> {
                       ),
                       child: PrimaryButton(
                         width: 210,
-                        desktopMed: true,
+                        buttonHeight: ButtonHeight.l,
                         enabled: true,
                         label: "Change language",
                         onPressed: () {
diff --git a/lib/pages_desktop_specific/home/settings_menu/security_settings.dart b/lib/pages_desktop_specific/home/settings_menu/security_settings.dart
index 9f870440b..f2853e6f5 100644
--- a/lib/pages_desktop_specific/home/settings_menu/security_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/security_settings.dart
@@ -485,7 +485,7 @@ class _SecuritySettings extends ConsumerState<SecuritySettings> {
                                   const SizedBox(height: 20),
                                   PrimaryButton(
                                     width: 160,
-                                    desktopMed: true,
+                                    buttonHeight: ButtonHeight.l,
                                     enabled: shouldEnableSave,
                                     label: "Save changes",
                                     onPressed: () async {
@@ -503,7 +503,7 @@ class _SecuritySettings extends ConsumerState<SecuritySettings> {
                             )
                           : PrimaryButton(
                               width: 210,
-                              desktopMed: true,
+                              buttonHeight: ButtonHeight.l,
                               enabled: true,
                               label: "Set up new password",
                               onPressed: () {
diff --git a/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart b/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart
index 408b93e15..ae11f5582 100644
--- a/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart
@@ -83,7 +83,7 @@ class _SyncingPreferencesSettings
                       ),
                       child: PrimaryButton(
                         width: 210,
-                        desktopMed: true,
+                        buttonHeight: ButtonHeight.l,
                         enabled: true,
                         label: "Change preferences",
                         onPressed: () {},
diff --git a/lib/widgets/desktop/custom_text_button.dart b/lib/widgets/desktop/custom_text_button.dart
index b96a697b8..90b75c459 100644
--- a/lib/widgets/desktop/custom_text_button.dart
+++ b/lib/widgets/desktop/custom_text_button.dart
@@ -1,6 +1,16 @@
 import 'package:flutter/material.dart';
 import 'package:stackwallet/utilities/util.dart';
 
+enum ButtonHeight {
+  xxs,
+  xs,
+  s,
+  m,
+  l,
+  xl,
+  xxl,
+}
+
 class CustomTextButtonBase extends StatelessWidget {
   const CustomTextButtonBase({
     Key? key,
diff --git a/lib/widgets/desktop/primary_button.dart b/lib/widgets/desktop/primary_button.dart
index f3c900c34..134ff36c3 100644
--- a/lib/widgets/desktop/primary_button.dart
+++ b/lib/widgets/desktop/primary_button.dart
@@ -4,6 +4,8 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/utilities/util.dart';
 import 'package:stackwallet/widgets/desktop/custom_text_button.dart';
 
+export 'package:stackwallet/widgets/desktop/custom_text_button.dart';
+
 class PrimaryButton extends StatelessWidget {
   const PrimaryButton({
     Key? key,
@@ -13,7 +15,7 @@ class PrimaryButton extends StatelessWidget {
     this.icon,
     this.onPressed,
     this.enabled = true,
-    this.desktopMed = false,
+    this.buttonHeight,
   }) : super(key: key);
 
   final double? width;
@@ -22,23 +24,44 @@ class PrimaryButton extends StatelessWidget {
   final VoidCallback? onPressed;
   final bool enabled;
   final Widget? icon;
-  final bool desktopMed;
+  final ButtonHeight? buttonHeight;
 
   TextStyle getStyle(bool isDesktop, BuildContext context) {
     if (isDesktop) {
-      if (desktopMed) {
-        return STextStyles.desktopTextExtraSmall(context).copyWith(
-          color: enabled
-              ? Theme.of(context).extension<StackColors>()!.buttonTextPrimary
-              : Theme.of(context)
-                  .extension<StackColors>()!
-                  .buttonTextPrimaryDisabled,
-        );
-      } else {
+      if (buttonHeight == null) {
         return enabled
             ? STextStyles.desktopButtonEnabled(context)
             : STextStyles.desktopButtonDisabled(context);
       }
+
+      switch (buttonHeight!) {
+        case ButtonHeight.xxs:
+        case ButtonHeight.xs:
+        case ButtonHeight.s:
+          return STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+            color: enabled
+                ? Theme.of(context).extension<StackColors>()!.buttonTextPrimary
+                : Theme.of(context)
+                    .extension<StackColors>()!
+                    .buttonTextPrimaryDisabled,
+          );
+
+        case ButtonHeight.m:
+        case ButtonHeight.l:
+          return STextStyles.desktopTextExtraSmall(context).copyWith(
+            color: enabled
+                ? Theme.of(context).extension<StackColors>()!.buttonTextPrimary
+                : Theme.of(context)
+                    .extension<StackColors>()!
+                    .buttonTextPrimaryDisabled,
+          );
+
+        case ButtonHeight.xl:
+        case ButtonHeight.xxl:
+          return enabled
+              ? STextStyles.desktopButtonEnabled(context)
+              : STextStyles.desktopButtonDisabled(context);
+      }
     } else {
       return STextStyles.button(context).copyWith(
         color: enabled
@@ -50,12 +73,51 @@ class PrimaryButton extends StatelessWidget {
     }
   }
 
+  double? _getHeight() {
+    if (buttonHeight == null) {
+      return height;
+    }
+
+    if (Util.isDesktop) {
+      switch (buttonHeight!) {
+        case ButtonHeight.xxs:
+          return 28;
+        case ButtonHeight.xs:
+          return 32;
+        case ButtonHeight.s:
+          return 40;
+        case ButtonHeight.m:
+          return 48;
+        case ButtonHeight.l:
+          return 56;
+        case ButtonHeight.xl:
+          return 70;
+        case ButtonHeight.xxl:
+          return 96;
+      }
+    } else {
+      switch (buttonHeight!) {
+        case ButtonHeight.xxs:
+        case ButtonHeight.xs:
+        case ButtonHeight.s:
+        case ButtonHeight.m:
+          return 28;
+        case ButtonHeight.l:
+          return 30;
+        case ButtonHeight.xl:
+          return 46;
+        case ButtonHeight.xxl:
+          return 56;
+      }
+    }
+  }
+
   @override
   Widget build(BuildContext context) {
     final isDesktop = Util.isDesktop;
 
     return CustomTextButtonBase(
-      height: desktopMed ? 56 : height,
+      height: _getHeight(),
       width: width,
       textButton: TextButton(
         onPressed: enabled ? onPressed : null,
diff --git a/lib/widgets/desktop/secondary_button.dart b/lib/widgets/desktop/secondary_button.dart
index 8d5eae0ce..7cf8e9f72 100644
--- a/lib/widgets/desktop/secondary_button.dart
+++ b/lib/widgets/desktop/secondary_button.dart
@@ -4,6 +4,8 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/utilities/util.dart';
 import 'package:stackwallet/widgets/desktop/custom_text_button.dart';
 
+export 'package:stackwallet/widgets/desktop/custom_text_button.dart';
+
 class SecondaryButton extends StatelessWidget {
   const SecondaryButton({
     Key? key,
@@ -13,7 +15,7 @@ class SecondaryButton extends StatelessWidget {
     this.icon,
     this.onPressed,
     this.enabled = true,
-    this.desktopMed = false,
+    this.buttonHeight,
   }) : super(key: key);
 
   final double? width;
@@ -22,23 +24,47 @@ class SecondaryButton extends StatelessWidget {
   final VoidCallback? onPressed;
   final bool enabled;
   final Widget? icon;
-  final bool desktopMed;
+  final ButtonHeight? buttonHeight;
 
   TextStyle getStyle(bool isDesktop, BuildContext context) {
     if (isDesktop) {
-      if (desktopMed) {
-        return STextStyles.desktopTextExtraSmall(context).copyWith(
-          color: enabled
-              ? Theme.of(context).extension<StackColors>()!.buttonTextSecondary
-              : Theme.of(context)
-                  .extension<StackColors>()!
-                  .buttonTextSecondaryDisabled,
-        );
-      } else {
+      if (buttonHeight == null) {
         return enabled
             ? STextStyles.desktopButtonSecondaryEnabled(context)
             : STextStyles.desktopButtonSecondaryDisabled(context);
       }
+      switch (buttonHeight!) {
+        case ButtonHeight.xxs:
+        case ButtonHeight.xs:
+        case ButtonHeight.s:
+          return STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+            color: enabled
+                ? Theme.of(context)
+                    .extension<StackColors>()!
+                    .buttonTextSecondary
+                : Theme.of(context)
+                    .extension<StackColors>()!
+                    .buttonTextSecondaryDisabled,
+          );
+
+        case ButtonHeight.m:
+        case ButtonHeight.l:
+          return STextStyles.desktopTextExtraSmall(context).copyWith(
+            color: enabled
+                ? Theme.of(context)
+                    .extension<StackColors>()!
+                    .buttonTextSecondary
+                : Theme.of(context)
+                    .extension<StackColors>()!
+                    .buttonTextSecondaryDisabled,
+          );
+
+        case ButtonHeight.xl:
+        case ButtonHeight.xxl:
+          return enabled
+              ? STextStyles.desktopButtonSecondaryEnabled(context)
+              : STextStyles.desktopButtonSecondaryDisabled(context);
+      }
     } else {
       return STextStyles.button(context).copyWith(
         color: enabled
@@ -50,12 +76,51 @@ class SecondaryButton extends StatelessWidget {
     }
   }
 
+  double? _getHeight() {
+    if (buttonHeight == null) {
+      return height;
+    }
+
+    if (Util.isDesktop) {
+      switch (buttonHeight!) {
+        case ButtonHeight.xxs:
+          return 28;
+        case ButtonHeight.xs:
+          return 32;
+        case ButtonHeight.s:
+          return 40;
+        case ButtonHeight.m:
+          return 48;
+        case ButtonHeight.l:
+          return 56;
+        case ButtonHeight.xl:
+          return 70;
+        case ButtonHeight.xxl:
+          return 96;
+      }
+    } else {
+      switch (buttonHeight!) {
+        case ButtonHeight.xxs:
+        case ButtonHeight.xs:
+        case ButtonHeight.s:
+        case ButtonHeight.m:
+          return 28;
+        case ButtonHeight.l:
+          return 30;
+        case ButtonHeight.xl:
+          return 46;
+        case ButtonHeight.xxl:
+          return 56;
+      }
+    }
+  }
+
   @override
   Widget build(BuildContext context) {
     final isDesktop = Util.isDesktop;
 
     return CustomTextButtonBase(
-      height: desktopMed ? 56 : height,
+      height: _getHeight(),
       width: width,
       textButton: TextButton(
         onPressed: enabled ? onPressed : null,

From 1d238c29f09207b975968c27707df5097de218ac Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 12:01:52 -0600
Subject: [PATCH 014/100] WIP: centralize button heights

---
 .../create_backup_view.dart                   |   4 +-
 .../restore_from_file_view.dart               |   4 +-
 .../wallet_view/desktop_wallet_view.dart      |   6 +-
 .../advanced_settings/advanced_settings.dart  | 111 +++++-------------
 .../backup_and_restore_settings.dart          |  10 +-
 .../currency_settings/currency_settings.dart  |   2 +-
 .../language_settings/language_settings.dart  |   4 +-
 .../home/settings_menu/security_settings.dart |   2 +-
 .../syncing_preferences_settings.dart         |   2 +-
 lib/widgets/desktop/primary_button.dart       |   4 +-
 lib/widgets/desktop/secondary_button.dart     |   4 +-
 11 files changed, 52 insertions(+), 101 deletions(-)

diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart
index 0609e4b1b..a6241d25a 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart
@@ -562,7 +562,7 @@ class _RestoreFromFileViewState extends State<CreateBackupView> {
                       Consumer(builder: (context, ref, __) {
                         return PrimaryButton(
                           width: 183,
-                          buttonHeight: ButtonHeight.l,
+                          buttonHeight: ButtonHeight.m,
                           label: "Create backup",
                           enabled: shouldEnableCreate,
                           onPressed: !shouldEnableCreate
@@ -780,7 +780,7 @@ class _RestoreFromFileViewState extends State<CreateBackupView> {
                       ),
                       SecondaryButton(
                         width: 183,
-                        buttonHeight: ButtonHeight.l,
+                        buttonHeight: ButtonHeight.m,
                         label: "Cancel",
                         onPressed: () {},
                       ),
diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart
index 9be6af4cb..d6571967d 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart
@@ -389,7 +389,7 @@ class _RestoreFromFileViewState extends ConsumerState<RestoreFromFileView> {
                       children: [
                         PrimaryButton(
                           width: 183,
-                          buttonHeight: ButtonHeight.l,
+                          buttonHeight: ButtonHeight.m,
                           label: "Restore",
                           enabled: !(passwordController.text.isEmpty ||
                               fileLocationController.text.isEmpty),
@@ -566,7 +566,7 @@ class _RestoreFromFileViewState extends ConsumerState<RestoreFromFileView> {
                         ),
                         SecondaryButton(
                           width: 183,
-                          buttonHeight: ButtonHeight.l,
+                          buttonHeight: ButtonHeight.m,
                           label: "Cancel",
                           onPressed: () {},
                         ),
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
index 952194244..d21a19aee 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
@@ -411,7 +411,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
                   if (coin == Coin.firo)
                     SecondaryButton(
                       width: 180,
-                      desktopMed: true,
+                      buttonHeight: ButtonHeight.l,
                       label: "Anonymize funds",
                       onPressed: () async {
                         await showDialog<void>(
@@ -441,7 +441,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
                                     children: [
                                       SecondaryButton(
                                         width: 180,
-                                        desktopMed: true,
+                                        buttonHeight: ButtonHeight.l,
                                         label: "Cancel",
                                         onPressed: () {
                                           Navigator.of(context).pop();
@@ -450,7 +450,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
                                       const SizedBox(width: 20),
                                       PrimaryButton(
                                         width: 180,
-                                        desktopMed: true,
+                                        buttonHeight: ButtonHeight.l,
                                         label: "Continue",
                                         onPressed: () {
                                           Navigator.of(context).pop();
diff --git a/lib/pages_desktop_specific/home/settings_menu/advanced_settings/advanced_settings.dart b/lib/pages_desktop_specific/home/settings_menu/advanced_settings/advanced_settings.dart
index b4ff3fe6a..621683e65 100644
--- a/lib/pages_desktop_specific/home/settings_menu/advanced_settings/advanced_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/advanced_settings/advanced_settings.dart
@@ -8,6 +8,7 @@ import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 
 import 'debug_info_dialog.dart';
@@ -143,7 +144,21 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
                                 ),
                               ],
                             ),
-                            const StackPrivacyButton(),
+                            PrimaryButton(
+                              label: "Change",
+                              buttonHeight: ButtonHeight.xs,
+                              width: 86,
+                              onPressed: () async {
+                                await showDialog<dynamic>(
+                                  context: context,
+                                  useSafeArea: false,
+                                  barrierDismissible: true,
+                                  builder: (context) {
+                                    return const StackPrivacyDialog();
+                                  },
+                                );
+                              },
+                            )
                           ],
                         ),
                       );
@@ -172,7 +187,21 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
                                     .textDark),
                         textAlign: TextAlign.left,
                       ),
-                      ShowLogsButton(),
+                      PrimaryButton(
+                        buttonHeight: ButtonHeight.xs,
+                        label: "Show logs",
+                        width: 101,
+                        onPressed: () async {
+                          await showDialog<dynamic>(
+                            context: context,
+                            useSafeArea: false,
+                            barrierDismissible: true,
+                            builder: (context) {
+                              return const DebugInfoDialog();
+                            },
+                          );
+                        },
+                      ),
                     ],
                   ),
                 ),
@@ -184,81 +213,3 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
     );
   }
 }
-
-class StackPrivacyButton extends ConsumerWidget {
-  const StackPrivacyButton({
-    Key? key,
-  }) : super(key: key);
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    Future<void> changePrivacySettings() async {
-      await showDialog<dynamic>(
-        context: context,
-        useSafeArea: false,
-        barrierDismissible: true,
-        builder: (context) {
-          return StackPrivacyDialog();
-        },
-      );
-    }
-
-    return SizedBox(
-      width: 84,
-      height: 37,
-      child: TextButton(
-        style: Theme.of(context)
-            .extension<StackColors>()!
-            .getPrimaryEnabledButtonColor(context),
-        onPressed: () {
-          // Navigator.of(context).pushNamed(
-          //   StackPrivacyCalls.routeName,
-          //   arguments: false,
-          // );
-          changePrivacySettings();
-        },
-        child: Text(
-          "Change",
-          style: STextStyles.desktopTextExtraExtraSmall(context)
-              .copyWith(color: Colors.white),
-        ),
-      ),
-    );
-  }
-}
-
-class ShowLogsButton extends ConsumerWidget {
-  const ShowLogsButton({
-    Key? key,
-  }) : super(key: key);
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    Future<void> viewDebugLogs() async {
-      await showDialog<dynamic>(
-        context: context,
-        useSafeArea: false,
-        barrierDismissible: true,
-        builder: (context) {
-          return const DebugInfoDialog();
-        },
-      );
-    }
-
-    return SizedBox(
-      width: 101,
-      height: 37,
-      child: TextButton(
-        style: Theme.of(context)
-            .extension<StackColors>()!
-            .getPrimaryEnabledButtonColor(context),
-        onPressed: () {
-          viewDebugLogs();
-        },
-        child: Text(
-          "Show logs",
-          style: STextStyles.desktopTextExtraExtraSmall(context)
-              .copyWith(color: Colors.white),
-        ),
-      ),
-    );
-  }
-}
diff --git a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/backup_and_restore_settings.dart b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/backup_and_restore_settings.dart
index 37f3f35a6..c82b5f923 100644
--- a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/backup_and_restore_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/backup_and_restore_settings.dart
@@ -422,7 +422,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                                 padding: const EdgeInsets.all(10),
                                 child: !isEnabledAutoBackup
                                     ? PrimaryButton(
-                                        buttonHeight: ButtonHeight.l,
+                                        buttonHeight: ButtonHeight.m,
                                         width: 200,
                                         label: "Enable auto backup",
                                         onPressed: () {
@@ -467,7 +467,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                                           Row(
                                             children: [
                                               PrimaryButton(
-                                                buttonHeight: ButtonHeight.l,
+                                                buttonHeight: ButtonHeight.m,
                                                 width: 190,
                                                 label: "Disable auto backup",
                                                 onPressed: () {
@@ -476,7 +476,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                                               ),
                                               const SizedBox(width: 16),
                                               SecondaryButton(
-                                                buttonHeight: ButtonHeight.l,
+                                                buttonHeight: ButtonHeight.m,
                                                 width: 190,
                                                 label: "Edit auto backup",
                                                 onPressed: () {
@@ -560,7 +560,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                                         child: CreateBackupView(),
                                       )
                                     : PrimaryButton(
-                                        buttonHeight: ButtonHeight.l,
+                                        buttonHeight: ButtonHeight.m,
                                         width: 200,
                                         label: "Create manual backup",
                                         onPressed: () {
@@ -642,7 +642,7 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
                                         child: RestoreFromFileView(),
                                       )
                                     : PrimaryButton(
-                                        buttonHeight: ButtonHeight.l,
+                                        buttonHeight: ButtonHeight.m,
                                         width: 200,
                                         label: "Restore backup",
                                         onPressed: () {
diff --git a/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart b/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart
index 0740157ad..d9c20d8fa 100644
--- a/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart
@@ -108,7 +108,7 @@ class _CurrencySettings extends ConsumerState<CurrencySettings> {
                       ),
                       child: PrimaryButton(
                         width: 210,
-                        buttonHeight: ButtonHeight.l,
+                        buttonHeight: ButtonHeight.m,
                         enabled: true,
                         label: "Change currency",
                         onPressed: () {
diff --git a/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart b/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart
index db636ba17..acddcb055 100644
--- a/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart
@@ -80,12 +80,12 @@ class _LanguageOptionSettings extends ConsumerState<LanguageOptionSettings> {
                   crossAxisAlignment: CrossAxisAlignment.start,
                   children: [
                     Padding(
-                      padding: EdgeInsets.all(
+                      padding: const EdgeInsets.all(
                         10,
                       ),
                       child: PrimaryButton(
                         width: 210,
-                        buttonHeight: ButtonHeight.l,
+                        buttonHeight: ButtonHeight.m,
                         enabled: true,
                         label: "Change language",
                         onPressed: () {
diff --git a/lib/pages_desktop_specific/home/settings_menu/security_settings.dart b/lib/pages_desktop_specific/home/settings_menu/security_settings.dart
index f2853e6f5..f6762afa1 100644
--- a/lib/pages_desktop_specific/home/settings_menu/security_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/security_settings.dart
@@ -503,7 +503,7 @@ class _SecuritySettings extends ConsumerState<SecuritySettings> {
                             )
                           : PrimaryButton(
                               width: 210,
-                              buttonHeight: ButtonHeight.l,
+                              buttonHeight: ButtonHeight.m,
                               enabled: true,
                               label: "Set up new password",
                               onPressed: () {
diff --git a/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart b/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart
index ae11f5582..815e506db 100644
--- a/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart
@@ -83,7 +83,7 @@ class _SyncingPreferencesSettings
                       ),
                       child: PrimaryButton(
                         width: 210,
-                        buttonHeight: ButtonHeight.l,
+                        buttonHeight: ButtonHeight.m,
                         enabled: true,
                         label: "Change preferences",
                         onPressed: () {},
diff --git a/lib/widgets/desktop/primary_button.dart b/lib/widgets/desktop/primary_button.dart
index 134ff36c3..9441168e7 100644
--- a/lib/widgets/desktop/primary_button.dart
+++ b/lib/widgets/desktop/primary_button.dart
@@ -81,9 +81,9 @@ class PrimaryButton extends StatelessWidget {
     if (Util.isDesktop) {
       switch (buttonHeight!) {
         case ButtonHeight.xxs:
-          return 28;
-        case ButtonHeight.xs:
           return 32;
+        case ButtonHeight.xs:
+          return 37;
         case ButtonHeight.s:
           return 40;
         case ButtonHeight.m:
diff --git a/lib/widgets/desktop/secondary_button.dart b/lib/widgets/desktop/secondary_button.dart
index 7cf8e9f72..62bd900dd 100644
--- a/lib/widgets/desktop/secondary_button.dart
+++ b/lib/widgets/desktop/secondary_button.dart
@@ -84,9 +84,9 @@ class SecondaryButton extends StatelessWidget {
     if (Util.isDesktop) {
       switch (buttonHeight!) {
         case ButtonHeight.xxs:
-          return 28;
-        case ButtonHeight.xs:
           return 32;
+        case ButtonHeight.xs:
+          return 37;
         case ButtonHeight.s:
           return 40;
         case ButtonHeight.m:

From 95a9fade38c065fb0d578b8ea92f4c83ca6b1a1a Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 12:17:55 -0600
Subject: [PATCH 015/100] desktop contact address details

---
 .../desktop_address_book.dart                 |   7 +-
 .../subwidgets/desktop_address_card.dart      |  75 ++++++++++++
 .../subwidgets/desktop_contact_details.dart   | 108 ++++++------------
 3 files changed, 116 insertions(+), 74 deletions(-)
 create mode 100644 lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart

diff --git a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
index f028a3424..fd25617e7 100644
--- a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
@@ -427,8 +427,11 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
                 ),
           details: currentContactId == null
               ? Container()
-              : DesktopContactDetails(
-                  contactId: currentContactId!,
+              : RoundedWhiteContainer(
+            padding: const EdgeInsets.all(24),
+                  child: DesktopContactDetails(
+                    contactId: currentContactId!,
+                  ),
                 ),
         ),
       ),
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
new file mode 100644
index 000000000..49b75a4a8
--- /dev/null
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
@@ -0,0 +1,75 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:stackwallet/models/contact_address_entry.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/enums/coin_enum.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
+
+class DesktopAddressCard extends StatelessWidget {
+  const DesktopAddressCard({
+    Key? key,
+    required this.entry,
+  }) : super(key: key);
+
+  final ContactAddressEntry entry;
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        SvgPicture.asset(
+          Assets.svg.iconFor(
+            coin: entry.coin,
+          ),
+          height: 32,
+          width: 32,
+        ),
+        const SizedBox(
+          width: 16,
+        ),
+        Flexible(
+          child: Column(
+            mainAxisSize: MainAxisSize.min,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              SelectableText(
+                "${entry.label} (${entry.coin.ticker})",
+                style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+                  color: Theme.of(context).extension<StackColors>()!.textDark,
+                ),
+              ),
+              const SizedBox(
+                height: 2,
+              ),
+              SelectableText(
+                entry.address,
+                style: STextStyles.desktopTextExtraExtraSmall(context),
+              ),
+              const SizedBox(
+                height: 8,
+              ),
+              Row(
+                children: [
+                  BlueTextButton(
+                    text: "Copy",
+                    onTap: () {},
+                  ),
+                  const SizedBox(
+                    width: 16,
+                  ),
+                  BlueTextButton(
+                    text: "Edit",
+                    onTap: () {},
+                  ),
+                ],
+              )
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
index 5184b2293..bc19fe3bd 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
@@ -1,14 +1,14 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
-import 'package:stackwallet/models/contact_address_entry.dart';
+import 'package:stackwallet/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart';
 import 'package:stackwallet/providers/global/address_book_service_provider.dart';
 import 'package:stackwallet/utilities/assets.dart';
-import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
 
 class DesktopContactDetails extends ConsumerStatefulWidget {
   const DesktopContactDetails({
@@ -74,6 +74,8 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
             ),
             SecondaryButton(
               label: "Options",
+              width: 86,
+              buttonHeight: ButtonHeight.xxs,
               onPressed: () {},
             ),
           ],
@@ -106,12 +108,38 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
                             ),
                           ],
                         ),
-                        Column(
-                          mainAxisSize: MainAxisSize.min,
-                          children: [
-                            ...contact.addresses
-                                .map((e) => AddressCard(entry: e)),
-                          ],
+                        const SizedBox(
+                          height: 12,
+                        ),
+                        RoundedWhiteContainer(
+                          padding: const EdgeInsets.all(0),
+                          borderColor: Theme.of(context)
+                              .extension<StackColors>()!
+                              .background,
+                          child: Column(
+                            mainAxisSize: MainAxisSize.min,
+                            children: [
+                              for (int i = 0; i < contact.addresses.length; i++)
+                                Column(
+                                  mainAxisSize: MainAxisSize.min,
+                                  children: [
+                                    if (i > 0)
+                                      Container(
+                                        color: Theme.of(context)
+                                            .extension<StackColors>()!
+                                            .background,
+                                        height: 1,
+                                      ),
+                                    Padding(
+                                      padding: const EdgeInsets.all(18),
+                                      child: DesktopAddressCard(
+                                        entry: contact.addresses[i],
+                                      ),
+                                    ),
+                                  ],
+                                ),
+                            ],
+                          ),
                         )
                       ],
                     ),
@@ -125,67 +153,3 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
     );
   }
 }
-
-class AddressCard extends StatelessWidget {
-  const AddressCard({
-    Key? key,
-    required this.entry,
-  }) : super(key: key);
-
-  final ContactAddressEntry entry;
-
-  @override
-  Widget build(BuildContext context) {
-    return Row(
-      children: [
-        SvgPicture.asset(
-          Assets.svg.iconFor(
-            coin: entry.coin,
-          ),
-          height: 32,
-          width: 32,
-        ),
-        const SizedBox(
-          width: 16,
-        ),
-        Column(
-          mainAxisSize: MainAxisSize.min,
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
-            SelectableText(
-              "${entry.label} ${entry.coin.ticker}",
-              style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
-                color: Theme.of(context).extension<StackColors>()!.textDark,
-              ),
-            ),
-            const SizedBox(
-              height: 2,
-            ),
-            SelectableText(
-              entry.address,
-              style: STextStyles.desktopTextExtraExtraSmall(context),
-            ),
-            const SizedBox(
-              height: 8,
-            ),
-            Row(
-              children: [
-                BlueTextButton(
-                  text: "Copy",
-                  onTap: () {},
-                ),
-                const SizedBox(
-                  width: 16,
-                ),
-                BlueTextButton(
-                  text: "Edit",
-                  onTap: () {},
-                ),
-              ],
-            )
-          ],
-        ),
-      ],
-    );
-  }
-}

From 682966dab83a391ef3224c67833cc0d333a0cba9 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Thu, 17 Nov 2022 14:08:06 -0700
Subject: [PATCH 016/100] desktop block explorer dialog

---
 .../transaction_details_view.dart             | 200 ++++++++++++------
 .../wallet_view/desktop_wallet_view.dart      |   4 +-
 2 files changed, 142 insertions(+), 62 deletions(-)

diff --git a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart
index 1c2fb8e5d..dc4e41152 100644
--- a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart
+++ b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart
@@ -30,6 +30,8 @@ import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/icon_widgets/copy_icon.dart';
 import 'package:stackwallet/widgets/icon_widgets/pencil_icon.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
@@ -154,60 +156,136 @@ class _TransactionDetailsViewState
 
   Future<bool> showExplorerWarning(String explorer) async {
     final bool? shouldContinue = await showDialog<bool>(
-      context: context,
-      barrierDismissible: false,
-      builder: (_) => StackDialog(
-        title: "Attention",
-        message:
-            "You are about to view this transaction in a block explorer. The explorer may log your IP address and link it to the transaction. Only proceed if you trust $explorer.",
-        icon: Row(
-          children: [
-            Consumer(builder: (_, ref, __) {
-              return Checkbox(
-                value: ref.watch(prefsChangeNotifierProvider
-                    .select((value) => value.hideBlockExplorerWarning)),
-                onChanged: (value) {
-                  if (value is bool) {
-                    ref
-                        .read(prefsChangeNotifierProvider)
-                        .hideBlockExplorerWarning = value;
-                    setState(() {});
-                  }
+        context: context,
+        barrierDismissible: false,
+        builder: (_) {
+          if (!isDesktop) {
+            return StackDialog(
+              title: "Attention",
+              message:
+                  "You are about to view this transaction in a block explorer. The explorer may log your IP address and link it to the transaction. Only proceed if you trust $explorer.",
+              icon: Row(
+                children: [
+                  Consumer(builder: (_, ref, __) {
+                    return Checkbox(
+                      value: ref.watch(prefsChangeNotifierProvider
+                          .select((value) => value.hideBlockExplorerWarning)),
+                      onChanged: (value) {
+                        if (value is bool) {
+                          ref
+                              .read(prefsChangeNotifierProvider)
+                              .hideBlockExplorerWarning = value;
+                          setState(() {});
+                        }
+                      },
+                    );
+                  }),
+                  Text(
+                    "Never show again",
+                    style: STextStyles.smallMed14(context),
+                  )
+                ],
+              ),
+              leftButton: TextButton(
+                onPressed: () {
+                  Navigator.of(context).pop(false);
                 },
-              );
-            }),
-            Text(
-              "Never show again",
-              style: STextStyles.smallMed14(context),
-            )
-          ],
-        ),
-        leftButton: TextButton(
-          onPressed: () {
-            Navigator.of(context).pop(false);
-          },
-          child: Text(
-            "Cancel",
-            style: STextStyles.button(context).copyWith(
-                color: Theme.of(context)
+                child: Text(
+                  "Cancel",
+                  style: STextStyles.button(context).copyWith(
+                      color: Theme.of(context)
+                          .extension<StackColors>()!
+                          .accentColorDark),
+                ),
+              ),
+              rightButton: TextButton(
+                style: Theme.of(context)
                     .extension<StackColors>()!
-                    .accentColorDark),
-          ),
-        ),
-        rightButton: TextButton(
-          style: Theme.of(context)
-              .extension<StackColors>()!
-              .getPrimaryEnabledButtonColor(context),
-          onPressed: () {
-            Navigator.of(context).pop(true);
-          },
-          child: Text(
-            "Continue",
-            style: STextStyles.button(context),
-          ),
-        ),
-      ),
-    );
+                    .getPrimaryEnabledButtonColor(context),
+                onPressed: () {
+                  Navigator.of(context).pop(true);
+                },
+                child: Text(
+                  "Continue",
+                  style: STextStyles.button(context),
+                ),
+              ),
+            );
+          } else {
+            return DesktopDialog(
+              maxWidth: 550,
+              maxHeight: 300,
+              child: Padding(
+                padding:
+                    const EdgeInsets.symmetric(horizontal: 32, vertical: 20),
+                child: Column(
+                  children: [
+                    Row(
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                      children: [
+                        Text(
+                          "Attention",
+                          style: STextStyles.desktopH2(context),
+                        ),
+                        Row(
+                          children: [
+                            Consumer(builder: (_, ref, __) {
+                              return Checkbox(
+                                value: ref.watch(prefsChangeNotifierProvider
+                                    .select((value) =>
+                                        value.hideBlockExplorerWarning)),
+                                onChanged: (value) {
+                                  if (value is bool) {
+                                    ref
+                                        .read(prefsChangeNotifierProvider)
+                                        .hideBlockExplorerWarning = value;
+                                    setState(() {});
+                                  }
+                                },
+                              );
+                            }),
+                            Text(
+                              "Never show again",
+                              style: STextStyles.smallMed14(context),
+                            )
+                          ],
+                        ),
+                      ],
+                    ),
+                    const SizedBox(height: 16),
+                    Text(
+                      "You are about to view this transaction in a block explorer. The explorer may log your IP address and link it to the transaction. Only proceed if you trust $explorer.",
+                      style: STextStyles.desktopTextSmall(context),
+                    ),
+                    const SizedBox(height: 35),
+                    Row(
+                      mainAxisAlignment: MainAxisAlignment.center,
+                      children: [
+                        SecondaryButton(
+                          width: 200,
+                          buttonHeight: ButtonHeight.l,
+                          label: "Cancel",
+                          onPressed: () {
+                            Navigator.of(context).pop(false);
+                          },
+                        ),
+                        const SizedBox(width: 20),
+                        PrimaryButton(
+                          width: 200,
+                          buttonHeight: ButtonHeight.l,
+                          label: "Continue",
+                          onPressed: () {
+                            Navigator.of(context).pop(true);
+                          },
+                        ),
+                      ],
+                    ),
+                  ],
+                ),
+              ),
+            );
+          }
+        });
     return shouldContinue ?? false;
   }
 
@@ -995,15 +1073,17 @@ class _TransactionDetailsViewState
                                                     .externalApplication,
                                               );
                                             } catch (_) {
-                                              unawaited(showDialog<void>(
-                                                context: context,
-                                                builder: (_) => StackOkDialog(
-                                                  title:
-                                                      "Could not open in block explorer",
-                                                  message:
-                                                      "Failed to open \"${uri.toString()}\"",
+                                              unawaited(
+                                                showDialog<void>(
+                                                  context: context,
+                                                  builder: (_) => StackOkDialog(
+                                                    title:
+                                                        "Could not open in block explorer",
+                                                    message:
+                                                        "Failed to open \"${uri.toString()}\"",
+                                                  ),
                                                 ),
-                                              ));
+                                              );
                                             } finally {
                                               // Future<void>.delayed(
                                               //   const Duration(seconds: 1),
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
index d21a19aee..a7de8fdf4 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
@@ -440,7 +440,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
                                     mainAxisAlignment: MainAxisAlignment.center,
                                     children: [
                                       SecondaryButton(
-                                        width: 180,
+                                        width: 200,
                                         buttonHeight: ButtonHeight.l,
                                         label: "Cancel",
                                         onPressed: () {
@@ -449,7 +449,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
                                       ),
                                       const SizedBox(width: 20),
                                       PrimaryButton(
-                                        width: 180,
+                                        width: 200,
                                         buttonHeight: ButtonHeight.l,
                                         label: "Continue",
                                         onPressed: () {

From 11735cdaf7d8e5393687c2ec89893a72908d7d8a Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 12:56:10 -0600
Subject: [PATCH 017/100] desktop emoji select

---
 .../subviews/add_address_book_entry_view.dart | 132 ++++--------
 lib/widgets/emoji_select_sheet.dart           | 188 ++++++++++--------
 2 files changed, 151 insertions(+), 169 deletions(-)

diff --git a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart
index 5835c80cd..0007f3d81 100644
--- a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart
+++ b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart
@@ -191,33 +191,33 @@ class _AddAddressBookEntryViewState
                           style: STextStyles.desktopH3(context),
                           textAlign: TextAlign.center,
                         ),
-                        const SizedBox(width: 10),
-                        AppBarIconButton(
-                          key:
-                              const Key("addAddressBookEntryFavoriteButtonKey"),
-                          size: 36,
-                          shadows: const [],
-                          color: Theme.of(context)
-                              .extension<StackColors>()!
-                              .background,
-                          icon: SvgPicture.asset(
-                            Assets.svg.star,
-                            color: _isFavorite
-                                ? Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .favoriteStarActive
-                                : Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .favoriteStarInactive,
-                            width: 20,
-                            height: 20,
-                          ),
-                          onPressed: () {
-                            setState(() {
-                              _isFavorite = !_isFavorite;
-                            });
-                          },
-                        ),
+                        // const SizedBox(width: 10),
+                        // AppBarIconButton(
+                        //   key:
+                        //       const Key("addAddressBookEntryFavoriteButtonKey"),
+                        //   size: 36,
+                        //   shadows: const [],
+                        //   color: Theme.of(context)
+                        //       .extension<StackColors>()!
+                        //       .background,
+                        //   icon: SvgPicture.asset(
+                        //     Assets.svg.star,
+                        //     color: _isFavorite
+                        //         ? Theme.of(context)
+                        //             .extension<StackColors>()!
+                        //             .favoriteStarActive
+                        //         : Theme.of(context)
+                        //             .extension<StackColors>()!
+                        //             .favoriteStarInactive,
+                        //     width: 20,
+                        //     height: 20,
+                        //   ),
+                        //   onPressed: () {
+                        //     setState(() {
+                        //       _isFavorite = !_isFavorite;
+                        //     });
+                        //   },
+                        // ),
                       ],
                     ),
                   ),
@@ -225,10 +225,11 @@ class _AddAddressBookEntryViewState
                 ],
               ),
               Expanded(
-                  child: Padding(
-                padding: const EdgeInsets.symmetric(horizontal: 10),
-                child: child,
-              )),
+                child: Padding(
+                  padding: const EdgeInsets.symmetric(horizontal: 10),
+                  child: child,
+                ),
+              ),
             ],
           );
         },
@@ -292,66 +293,17 @@ class _AddAddressBookEntryViewState
                                           : showDialog<dynamic>(
                                               context: context,
                                               builder: (context) {
-                                                return DesktopDialog(
+                                                return const DesktopDialog(
                                                   maxHeight: 700,
-                                                  maxWidth: 700,
-                                                  child: Column(
-                                                    children: [
-                                                      Row(
-                                                        children: [
-                                                          Padding(
-                                                            padding:
-                                                                const EdgeInsets
-                                                                    .all(32),
-                                                            child: Text(
-                                                              "Select emoji",
-                                                              style: STextStyles
-                                                                  .desktopH3(
-                                                                      context),
-                                                              textAlign:
-                                                                  TextAlign
-                                                                      .center,
-                                                            ),
-                                                          ),
-                                                        ],
-                                                      ),
-                                                      Expanded(
-                                                        child: LayoutBuilder(
-                                                          builder: (context,
-                                                              constraints) {
-                                                            return SingleChildScrollView(
-                                                              scrollDirection:
-                                                                  Axis.vertical,
-                                                              child:
-                                                                  ConstrainedBox(
-                                                                constraints:
-                                                                    BoxConstraints(
-                                                                  minHeight:
-                                                                      constraints
-                                                                          .maxHeight,
-                                                                  minWidth:
-                                                                      constraints
-                                                                          .maxWidth,
-                                                                ),
-                                                                child:
-                                                                    IntrinsicHeight(
-                                                                  child: Column(
-                                                                    children: const [
-                                                                      Padding(
-                                                                        padding:
-                                                                            EdgeInsets.symmetric(horizontal: 32),
-                                                                        // child:
-                                                                        //     EmojiSelectSheet(),
-                                                                      ),
-                                                                    ],
-                                                                  ),
-                                                                ),
-                                                              ),
-                                                            );
-                                                          },
-                                                        ),
-                                                      ),
-                                                    ],
+                                                  maxWidth: 600,
+                                                  child: Padding(
+                                                    padding: EdgeInsets.only(
+                                                      left: 32,
+                                                      right: 20,
+                                                      top: 32,
+                                                      bottom: 32,
+                                                    ),
+                                                    child: EmojiSelectSheet(),
                                                   ),
                                                 );
                                               }).then((value) {
diff --git a/lib/widgets/emoji_select_sheet.dart b/lib/widgets/emoji_select_sheet.dart
index 85a90fec8..7bf02e967 100644
--- a/lib/widgets/emoji_select_sheet.dart
+++ b/lib/widgets/emoji_select_sheet.dart
@@ -4,6 +4,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 
 class EmojiSelectSheet extends ConsumerWidget {
   const EmojiSelectSheet({
@@ -16,7 +19,9 @@ class EmojiSelectSheet extends ConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final size = MediaQuery.of(context).size;
+    final isDesktop = Util.isDesktop;
+
+    final size = isDesktop ? const Size(600, 700) : MediaQuery.of(context).size;
     final double maxHeight = size.height * 0.60;
     final double availableWidth = size.width - (2 * horizontalPadding);
     final int emojisPerRow =
@@ -24,90 +29,115 @@ class EmojiSelectSheet extends ConsumerWidget {
 
     final itemCount = Emoji.all().length;
 
-    return Container(
-      decoration: BoxDecoration(
-        color: Theme.of(context).extension<StackColors>()!.popupBG,
-        borderRadius: const BorderRadius.vertical(
-          top: Radius.circular(20),
+    return ConditionalParent(
+      condition: !isDesktop,
+      builder: (child) => Container(
+        decoration: BoxDecoration(
+          color: Theme.of(context).extension<StackColors>()!.popupBG,
+          borderRadius: const BorderRadius.vertical(
+            top: Radius.circular(20),
+          ),
+        ),
+        child: LimitedBox(
+          maxHeight: maxHeight,
+          child: Padding(
+            padding: EdgeInsets.only(
+              left: horizontalPadding,
+              right: horizontalPadding,
+              top: 10,
+              bottom: 0,
+            ),
+            child: child,
+          ),
         ),
       ),
-      child: LimitedBox(
-        maxHeight: maxHeight,
-        child: Padding(
-          padding: EdgeInsets.only(
-            left: horizontalPadding,
-            right: horizontalPadding,
-            top: 10,
-            bottom: 0,
-          ),
-          child: Column(
-            mainAxisSize: MainAxisSize.min,
-            crossAxisAlignment: CrossAxisAlignment.stretch,
-            children: [
-              Center(
-                child: Container(
-                  decoration: BoxDecoration(
-                    color: Theme.of(context)
-                        .extension<StackColors>()!
-                        .textFieldDefaultBG,
-                    borderRadius: BorderRadius.circular(
-                      Constants.size.circularBorderRadius,
-                    ),
+      child: Column(
+        mainAxisSize: MainAxisSize.min,
+        crossAxisAlignment: CrossAxisAlignment.stretch,
+        children: [
+          if (!isDesktop)
+            Center(
+              child: Container(
+                decoration: BoxDecoration(
+                  color: Theme.of(context)
+                      .extension<StackColors>()!
+                      .textFieldDefaultBG,
+                  borderRadius: BorderRadius.circular(
+                    Constants.size.circularBorderRadius,
                   ),
-                  width: 60,
-                  height: 4,
                 ),
+                width: 60,
+                height: 4,
               ),
-              const SizedBox(
-                height: 36,
-              ),
-              Text(
-                "Select emoji",
-                style: STextStyles.pageTitleH2(context),
-                textAlign: TextAlign.left,
-              ),
-              const SizedBox(
-                height: 16,
-              ),
-              Flexible(
-                child: Row(
-                  mainAxisAlignment: MainAxisAlignment.center,
-                  children: [
-                    Flexible(
-                      child: GridView.builder(
-                        itemCount: itemCount,
-                        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
-                          crossAxisCount: emojisPerRow,
-                        ),
-                        itemBuilder: (context, index) {
-                          final emoji = Emoji.all()[index];
-                          return GestureDetector(
-                            onTap: () {
-                              Navigator.of(context).pop(emoji);
-                            },
-                            child: Container(
-                              decoration: BoxDecoration(
-                                borderRadius: BorderRadius.circular(100),
-                                color: Colors.transparent,
-                              ),
-                              child: Padding(
-                                padding: const EdgeInsets.all(8.0),
-                                child: Text(emoji.char),
-                              ),
-                            ),
-                          );
-                        },
-                      ),
-                    )
-                  ],
-                ),
-              ),
-              const SizedBox(
-                height: 24,
-              ),
-            ],
+            ),
+          if (!isDesktop)
+            const SizedBox(
+              height: 36,
+            ),
+          Text(
+            "Select emoji",
+            style: isDesktop
+                ? STextStyles.desktopH3(context)
+                : STextStyles.pageTitleH2(context),
+            textAlign: TextAlign.left,
           ),
-        ),
+          SizedBox(
+            height: isDesktop ? 28 : 16,
+          ),
+          Flexible(
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.center,
+              children: [
+                Flexible(
+                  child: GridView.builder(
+                    itemCount: itemCount,
+                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
+                      crossAxisCount: emojisPerRow,
+                    ),
+                    itemBuilder: (context, index) {
+                      final emoji = Emoji.all()[index];
+                      return GestureDetector(
+                        onTap: () {
+                          Navigator.of(context).pop(emoji);
+                        },
+                        child: Container(
+                          decoration: BoxDecoration(
+                            borderRadius: BorderRadius.circular(100),
+                            color: Colors.transparent,
+                          ),
+                          child: Padding(
+                            padding: const EdgeInsets.all(8.0),
+                            child: Text(
+                              emoji.char,
+                              style: isDesktop
+                                  ? STextStyles.desktopTextSmall(context)
+                                  : null,
+                            ),
+                          ),
+                        ),
+                      );
+                    },
+                  ),
+                )
+              ],
+            ),
+          ),
+          SizedBox(
+            height: isDesktop ? 20 : 24,
+          ),
+          if (isDesktop)
+            Row(
+              mainAxisAlignment: MainAxisAlignment.end,
+              children: [
+                SecondaryButton(
+                  label: "Cancel",
+                  width: 248,
+                  buttonHeight: ButtonHeight.l,
+                  onPressed: Navigator.of(context).pop,
+                ),
+              ],
+            ),
+        ],
       ),
     );
   }

From 134087bfc4c18c3482e49d6b1e7a16b9f0a78032 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 13:15:57 -0600
Subject: [PATCH 018/100] desktop add contact popup tweaks

---
 .../subviews/add_address_book_entry_view.dart | 375 ++++++------------
 .../new_contact_address_entry_form.dart       |   2 +-
 2 files changed, 121 insertions(+), 256 deletions(-)

diff --git a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart
index 0007f3d81..bb93c68d8 100644
--- a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart
+++ b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart
@@ -21,6 +21,8 @@ import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/emoji_select_sheet.dart';
 import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
@@ -191,33 +193,6 @@ class _AddAddressBookEntryViewState
                           style: STextStyles.desktopH3(context),
                           textAlign: TextAlign.center,
                         ),
-                        // const SizedBox(width: 10),
-                        // AppBarIconButton(
-                        //   key:
-                        //       const Key("addAddressBookEntryFavoriteButtonKey"),
-                        //   size: 36,
-                        //   shadows: const [],
-                        //   color: Theme.of(context)
-                        //       .extension<StackColors>()!
-                        //       .background,
-                        //   icon: SvgPicture.asset(
-                        //     Assets.svg.star,
-                        //     color: _isFavorite
-                        //         ? Theme.of(context)
-                        //             .extension<StackColors>()!
-                        //             .favoriteStarActive
-                        //         : Theme.of(context)
-                        //             .extension<StackColors>()!
-                        //             .favoriteStarInactive,
-                        //     width: 20,
-                        //     height: 20,
-                        //   ),
-                        //   onPressed: () {
-                        //     setState(() {
-                        //       _isFavorite = !_isFavorite;
-                        //     });
-                        //   },
-                        // ),
                       ],
                     ),
                   ),
@@ -226,7 +201,11 @@ class _AddAddressBookEntryViewState
               ),
               Expanded(
                 child: Padding(
-                  padding: const EdgeInsets.symmetric(horizontal: 10),
+                  padding: const EdgeInsets.only(
+                    left: 10,
+                    right: 10,
+                    bottom: 32,
+                  ),
                   child: child,
                 ),
               ),
@@ -239,16 +218,17 @@ class _AddAddressBookEntryViewState
               padding: const EdgeInsets.symmetric(horizontal: 12),
               child: SingleChildScrollView(
                 controller: scrollController,
-                padding: const EdgeInsets.only(
+                padding: EdgeInsets.only(
                   // top: 8,
                   left: 4,
                   right: 4,
-                  bottom: 16,
+                  bottom: isDesktop ? 0 : 16,
                 ),
                 child: ConstrainedBox(
                   constraints: BoxConstraints(
                     // subtract top and bottom padding set in parent
-                    minHeight: constraint.maxHeight - 16, // - 8,
+                    minHeight:
+                        constraint.maxHeight - (isDesktop ? 0 : 16), // - 8,
                   ),
                   child: IntrinsicHeight(
                     child: Column(
@@ -259,38 +239,21 @@ class _AddAddressBookEntryViewState
                                 mainAxisAlignment:
                                     MainAxisAlignment.spaceBetween,
                                 children: [
-                                  GestureDetector(
-                                    onTap: () {
-                                      if (_selectedEmoji != null) {
-                                        setState(() {
-                                          _selectedEmoji = null;
-                                        });
-                                        return;
-                                      }
+                                  SizedBox(
+                                    height: 56,
+                                    width: 56,
+                                    child: MouseRegion(
+                                      cursor: SystemMouseCursors.click,
+                                      child: GestureDetector(
+                                        onTap: () {
+                                          if (_selectedEmoji != null) {
+                                            setState(() {
+                                              _selectedEmoji = null;
+                                            });
+                                            return;
+                                          }
 
-                                      ///TODO if desktop make dialog
-                                      !isDesktop
-                                          ? showModalBottomSheet<dynamic>(
-                                              backgroundColor:
-                                                  Colors.transparent,
-                                              context: context,
-                                              shape:
-                                                  const RoundedRectangleBorder(
-                                                borderRadius:
-                                                    BorderRadius.vertical(
-                                                  top: Radius.circular(20),
-                                                ),
-                                              ),
-                                              builder: (_) =>
-                                                  const EmojiSelectSheet(),
-                                            ).then((value) {
-                                              if (value is Emoji) {
-                                                setState(() {
-                                                  _selectedEmoji = value;
-                                                });
-                                              }
-                                            })
-                                          : showDialog<dynamic>(
+                                          showDialog<dynamic>(
                                               context: context,
                                               builder: (context) {
                                                 return const DesktopDialog(
@@ -307,77 +270,80 @@ class _AddAddressBookEntryViewState
                                                   ),
                                                 );
                                               }).then((value) {
-                                              if (value is Emoji) {
-                                                setState(() {
-                                                  _selectedEmoji = value;
-                                                });
-                                              }
-                                            });
-                                    },
-                                    child: SizedBox(
-                                      height: 56,
-                                      width: 56,
-                                      child: Stack(
-                                        children: [
-                                          Container(
-                                            height: 56,
-                                            width: 56,
-                                            decoration: BoxDecoration(
-                                              borderRadius:
-                                                  BorderRadius.circular(24),
-                                              color: Theme.of(context)
-                                                  .extension<StackColors>()!
-                                                  .textFieldActiveBG,
-                                            ),
-                                            child: Center(
-                                              child: _selectedEmoji == null
-                                                  ? SvgPicture.asset(
-                                                      Assets.svg.user,
-                                                      height: 30,
-                                                      width: 30,
-                                                    )
-                                                  : Text(
-                                                      _selectedEmoji!.char,
-                                                      style: STextStyles
-                                                          .pageTitleH1(context),
-                                                    ),
-                                            ),
-                                          ),
-                                          Align(
-                                            alignment: Alignment.bottomRight,
-                                            child: Container(
-                                              height: 14,
-                                              width: 14,
+                                            if (value is Emoji) {
+                                              setState(() {
+                                                _selectedEmoji = value;
+                                              });
+                                            }
+                                          });
+                                        },
+                                        child: Stack(
+                                          children: [
+                                            Container(
+                                              height: 56,
+                                              width: 56,
                                               decoration: BoxDecoration(
-                                                  borderRadius:
-                                                      BorderRadius.circular(14),
-                                                  color: Theme.of(context)
-                                                      .extension<StackColors>()!
-                                                      .accentColorDark),
+                                                borderRadius:
+                                                    BorderRadius.circular(100),
+                                                color: Theme.of(context)
+                                                    .extension<StackColors>()!
+                                                    .textFieldActiveBG,
+                                              ),
                                               child: Center(
                                                 child: _selectedEmoji == null
                                                     ? SvgPicture.asset(
-                                                        Assets.svg.plus,
-                                                        color: Theme.of(context)
-                                                            .extension<
-                                                                StackColors>()!
-                                                            .textWhite,
-                                                        width: 12,
-                                                        height: 12,
+                                                        Assets.svg.user,
+                                                        height: 30,
+                                                        width: 30,
                                                       )
-                                                    : SvgPicture.asset(
-                                                        Assets.svg.thickX,
-                                                        color: Theme.of(context)
-                                                            .extension<
-                                                                StackColors>()!
-                                                            .textWhite,
-                                                        width: 8,
-                                                        height: 8,
+                                                    : Text(
+                                                        _selectedEmoji!.char,
+                                                        style: STextStyles
+                                                            .pageTitleH1(
+                                                                context),
                                                       ),
                                               ),
                                             ),
-                                          )
-                                        ],
+                                            Align(
+                                              alignment: Alignment.bottomRight,
+                                              child: Container(
+                                                height: 14,
+                                                width: 14,
+                                                decoration: BoxDecoration(
+                                                    borderRadius:
+                                                        BorderRadius.circular(
+                                                            14),
+                                                    color: Theme.of(context)
+                                                        .extension<
+                                                            StackColors>()!
+                                                        .accentColorDark),
+                                                child: Center(
+                                                  child: _selectedEmoji == null
+                                                      ? SvgPicture.asset(
+                                                          Assets.svg.plus,
+                                                          color: Theme.of(
+                                                                  context)
+                                                              .extension<
+                                                                  StackColors>()!
+                                                              .textWhite,
+                                                          width: 12,
+                                                          height: 12,
+                                                        )
+                                                      : SvgPicture.asset(
+                                                          Assets.svg.thickX,
+                                                          color: Theme.of(
+                                                                  context)
+                                                              .extension<
+                                                                  StackColors>()!
+                                                              .textWhite,
+                                                          width: 8,
+                                                          height: 8,
+                                                        ),
+                                                ),
+                                              ),
+                                            )
+                                          ],
+                                        ),
                                       ),
                                     ),
                                   ),
@@ -453,100 +419,23 @@ class _AddAddressBookEntryViewState
                                         return;
                                       }
 
-                                      ///TODO if desktop make dialog
-                                      !isDesktop
-                                          ? showModalBottomSheet<dynamic>(
-                                              backgroundColor:
-                                                  Colors.transparent,
-                                              context: context,
-                                              shape:
-                                                  const RoundedRectangleBorder(
-                                                borderRadius:
-                                                    BorderRadius.vertical(
-                                                  top: Radius.circular(20),
-                                                ),
-                                              ),
-                                              builder: (_) =>
-                                                  const EmojiSelectSheet(),
-                                            ).then((value) {
-                                              if (value is Emoji) {
-                                                setState(() {
-                                                  _selectedEmoji = value;
-                                                });
-                                              }
-                                            })
-                                          : showDialog<dynamic>(
-                                              context: context,
-                                              builder: (context) {
-                                                return DesktopDialog(
-                                                  maxHeight: 700,
-                                                  maxWidth: 700,
-                                                  child: Column(
-                                                    children: [
-                                                      Row(
-                                                        children: [
-                                                          Padding(
-                                                            padding:
-                                                                const EdgeInsets
-                                                                    .all(32),
-                                                            child: Text(
-                                                              "Select emoji",
-                                                              style: STextStyles
-                                                                  .desktopH3(
-                                                                      context),
-                                                              textAlign:
-                                                                  TextAlign
-                                                                      .center,
-                                                            ),
-                                                          ),
-                                                        ],
-                                                      ),
-                                                      Expanded(
-                                                        child: LayoutBuilder(
-                                                          builder: (context,
-                                                              constraints) {
-                                                            return SingleChildScrollView(
-                                                              scrollDirection:
-                                                                  Axis.vertical,
-                                                              child:
-                                                                  ConstrainedBox(
-                                                                constraints:
-                                                                    BoxConstraints(
-                                                                  minHeight:
-                                                                      constraints
-                                                                          .maxHeight,
-                                                                  minWidth:
-                                                                      constraints
-                                                                          .maxWidth,
-                                                                ),
-                                                                child:
-                                                                    IntrinsicHeight(
-                                                                  child: Column(
-                                                                    children: const [
-                                                                      Padding(
-                                                                        padding:
-                                                                            EdgeInsets.symmetric(horizontal: 32),
-                                                                        // child:
-                                                                        //     EmojiSelectSheet(),
-                                                                      ),
-                                                                    ],
-                                                                  ),
-                                                                ),
-                                                              ),
-                                                            );
-                                                          },
-                                                        ),
-                                                      ),
-                                                    ],
-                                                  ),
-                                                );
-                                              }).then((value) {
-                                              if (value is Emoji) {
-                                                setState(() {
-                                                  _selectedEmoji = value;
-                                                });
-                                              }
-                                            });
+                                      showModalBottomSheet<dynamic>(
+                                        backgroundColor: Colors.transparent,
+                                        context: context,
+                                        shape: const RoundedRectangleBorder(
+                                          borderRadius: BorderRadius.vertical(
+                                            top: Radius.circular(20),
+                                          ),
+                                        ),
+                                        builder: (_) =>
+                                            const EmojiSelectSheet(),
+                                      ).then((value) {
+                                        if (value is Emoji) {
+                                          setState(() {
+                                            _selectedEmoji = value;
+                                          });
+                                        }
+                                      });
                                     },
                                     child: SizedBox(
                                       height: 48,
@@ -734,22 +623,16 @@ class _AddAddressBookEntryViewState
                         Row(
                           children: [
                             Expanded(
-                              child: TextButton(
-                                style: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .getSecondaryEnabledButtonColor(context),
-                                child: Text(
-                                  "Cancel",
-                                  style: STextStyles.button(context).copyWith(
-                                      color: Theme.of(context)
-                                          .extension<StackColors>()!
-                                          .accentColorDark),
-                                ),
+                              child: SecondaryButton(
+                                label: "Cancel",
+                                buttonHeight: isDesktop ? ButtonHeight.m : null,
                                 onPressed: () async {
-                                  if (FocusScope.of(context).hasFocus) {
+                                  if (!isDesktop &&
+                                      FocusScope.of(context).hasFocus) {
                                     FocusScope.of(context).unfocus();
                                     await Future<void>.delayed(
-                                        const Duration(milliseconds: 75));
+                                      const Duration(milliseconds: 75),
+                                    );
                                   }
                                   if (mounted) {
                                     Navigator.of(context).pop();
@@ -776,16 +659,11 @@ class _AddAddressBookEntryViewState
                                   bool shouldEnableSave =
                                       validForms && nameExists;
 
-                                  return TextButton(
-                                    style: shouldEnableSave
-                                        ? Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .getPrimaryEnabledButtonColor(
-                                                context)
-                                        : Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .getPrimaryDisabledButtonColor(
-                                                context),
+                                  return PrimaryButton(
+                                    label: "Save",
+                                    buttonHeight:
+                                        isDesktop ? ButtonHeight.m : null,
+                                    enabled: shouldEnableSave,
                                     onPressed: shouldEnableSave
                                         ? () async {
                                             if (FocusScope.of(context)
@@ -827,19 +705,6 @@ class _AddAddressBookEntryViewState
                                             }
                                           }
                                         : null,
-                                    child: Text(
-                                      "Save",
-                                      style:
-                                          STextStyles.button(context).copyWith(
-                                        color: shouldEnableSave
-                                            ? Theme.of(context)
-                                                .extension<StackColors>()!
-                                                .buttonTextPrimary
-                                            : Theme.of(context)
-                                                .extension<StackColors>()!
-                                                .buttonTextPrimaryDisabled,
-                                      ),
-                                    ),
                                   );
                                 },
                               ),
diff --git a/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart b/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart
index b6cf0aad4..f49547858 100644
--- a/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart
+++ b/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart
@@ -253,7 +253,7 @@ class _NewContactAddressEntryFormState
                         },
                         child: const ClipboardIcon(),
                       ),
-                    if (ref.watch(addressEntryDataProvider(widget.id)
+                    if (!Util.isDesktop && ref.watch(addressEntryDataProvider(widget.id)
                             .select((value) => value.address)) ==
                         null)
                       TextFieldIconButton(

From 0503999fa708aa0b7ab38d39c044d87435e045de Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 15:24:28 -0600
Subject: [PATCH 019/100] WIP coin dropdown

---
 .../new_contact_address_entry_form.dart       | 245 ++++++++++++------
 1 file changed, 172 insertions(+), 73 deletions(-)

diff --git a/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart b/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart
index f49547858..25cff073b 100644
--- a/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart
+++ b/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart
@@ -1,8 +1,10 @@
+import 'package:dropdown_button2/dropdown_button2.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/svg.dart';
 import 'package:stackwallet/pages/address_book_views/subviews/coin_select_sheet.dart';
+import 'package:stackwallet/providers/providers.dart';
 // import 'package:stackwallet/providers/global/should_show_lockscreen_on_resume_state_provider.dart';
 import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
 import 'package:stackwallet/utilities/address_utils.dart';
@@ -47,6 +49,8 @@ class _NewContactAddressEntryFormState
   late final FocusNode addressLabelFocusNode;
   late final FocusNode addressFocusNode;
 
+  List<Coin> coins = [];
+
   @override
   void initState() {
     addressLabelController = TextEditingController()
@@ -55,6 +59,7 @@ class _NewContactAddressEntryFormState
       ..text = ref.read(addressEntryDataProvider(widget.id)).address ?? "";
     addressLabelFocusNode = FocusNode();
     addressFocusNode = FocusNode();
+    coins = [...Coin.values];
     super.initState();
   }
 
@@ -70,86 +75,179 @@ class _NewContactAddressEntryFormState
   @override
   Widget build(BuildContext context) {
     final isDesktop = Util.isDesktop;
+    bool showTestNet = ref.watch(
+      prefsChangeNotifierProvider.select((value) => value.showTestNetCoins),
+    );
+    if (isDesktop) {
+      coins = [...Coin.values];
+
+      coins.remove(Coin.firoTestNet);
+      if (showTestNet) {
+        coins = coins.sublist(0, coins.length - kTestNetCoinCount);
+      }
+    }
+
     return Column(
       children: [
-        TextField(
-          autocorrect: Util.isDesktop ? false : true,
-          enableSuggestions: Util.isDesktop ? false : true,
-          readOnly: true,
-          style: STextStyles.field(context),
-          decoration: InputDecoration(
-            hintText: "Select cryptocurrency",
-            hintStyle: STextStyles.fieldLabel(context),
-            prefixIcon: Center(
-              child: Padding(
-                padding: const EdgeInsets.symmetric(horizontal: 12),
-                child: RawMaterialButton(
-                  splashColor:
-                      Theme.of(context).extension<StackColors>()!.highlight,
-                  shape: RoundedRectangleBorder(
-                    borderRadius: BorderRadius.circular(
-                      Constants.size.circularBorderRadius,
+        if (isDesktop)
+          DropdownButtonHideUnderline(
+            child: DropdownButton2<Coin>(
+              hint: Text(
+                "Select cryptocurrency",
+                style: STextStyles.fieldLabel(context),
+              ),
+              offset: const Offset(0, -10),
+              isExpanded: true,
+              dropdownElevation: 0,
+              value: ref.watch(addressEntryDataProvider(widget.id)
+                  .select((value) => value.coin)),
+              onChanged: (value) {
+                if (value is Coin) {
+                  ref.read(addressEntryDataProvider(widget.id)).coin = value;
+                }
+              },
+              icon: SvgPicture.asset(
+                Assets.svg.chevronDown,
+                width: 10,
+                height: 5,
+                color: Theme.of(context).extension<StackColors>()!.textDark3,
+              ),
+              buttonPadding: const EdgeInsets.symmetric(
+                horizontal: 16,
+                vertical: 4,
+              ),
+              buttonDecoration: BoxDecoration(
+                color: Theme.of(context)
+                    .extension<StackColors>()!
+                    .textFieldDefaultBG,
+                borderRadius: BorderRadius.circular(
+                  Constants.size.circularBorderRadius,
+                ),
+              ),
+              dropdownDecoration: BoxDecoration(
+                color: Theme.of(context)
+                    .extension<StackColors>()!
+                    .textFieldDefaultBG,
+                borderRadius: BorderRadius.circular(
+                  Constants.size.circularBorderRadius,
+                ),
+              ),
+              items: [
+                ...coins.map(
+                  (coin) => DropdownMenuItem<Coin>(
+                    value: coin,
+                    child: Padding(
+                      padding: const EdgeInsets.symmetric(vertical: 4),
+                      child: Row(
+                        children: [
+                          SvgPicture.asset(
+                            Assets.svg.iconFor(coin: coin),
+                            height: 24,
+                            width: 24,
+                          ),
+                          const SizedBox(
+                            width: 12,
+                          ),
+                          Text(
+                            coin.prettyName,
+                            style:
+                                STextStyles.desktopTextExtraExtraSmall(context)
+                                    .copyWith(
+                              color: Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textDark,
+                            ),
+                          ),
+                        ],
+                      ),
                     ),
                   ),
-                  onPressed: () {
-                    showModalBottomSheet<dynamic>(
-                      backgroundColor: Colors.transparent,
-                      context: context,
-                      builder: (_) => const CoinSelectSheet(),
-                    ).then((value) {
-                      if (value is Coin) {
-                        ref.read(addressEntryDataProvider(widget.id)).coin =
-                            value;
-                      }
-                    });
-                  },
-                  child: Row(
-                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                    children: [
-                      ref.watch(addressEntryDataProvider(widget.id)
-                                  .select((value) => value.coin)) ==
-                              null
-                          ? Text(
-                              "Select cryptocurrency",
-                              style: STextStyles.fieldLabel(context),
-                            )
-                          : Row(
-                              children: [
-                                SvgPicture.asset(
-                                  Assets.svg.iconFor(
-                                      coin: ref.watch(
-                                          addressEntryDataProvider(widget.id)
-                                              .select((value) => value.coin))!),
-                                  height: 20,
-                                  width: 20,
-                                ),
-                                const SizedBox(
-                                  width: 12,
-                                ),
-                                Text(
-                                  ref
-                                      .watch(addressEntryDataProvider(widget.id)
-                                          .select((value) => value.coin))!
-                                      .prettyName,
-                                  style: STextStyles.itemSubtitle12(context),
-                                ),
-                              ],
-                            ),
-                      SvgPicture.asset(
-                        Assets.svg.chevronDown,
-                        width: 8,
-                        height: 4,
-                        color: Theme.of(context)
-                            .extension<StackColors>()!
-                            .textSubtitle2,
+                ),
+              ],
+            ),
+          ),
+        if (!isDesktop)
+          TextField(
+            autocorrect: Util.isDesktop ? false : true,
+            enableSuggestions: Util.isDesktop ? false : true,
+            readOnly: true,
+            style: STextStyles.field(context),
+            decoration: InputDecoration(
+              hintText: "Select cryptocurrency",
+              hintStyle: STextStyles.fieldLabel(context),
+              prefixIcon: Center(
+                child: Padding(
+                  padding: const EdgeInsets.symmetric(horizontal: 12),
+                  child: RawMaterialButton(
+                    splashColor:
+                        Theme.of(context).extension<StackColors>()!.highlight,
+                    shape: RoundedRectangleBorder(
+                      borderRadius: BorderRadius.circular(
+                        Constants.size.circularBorderRadius,
                       ),
-                    ],
+                    ),
+                    onPressed: () {
+                      showModalBottomSheet<dynamic>(
+                        backgroundColor: Colors.transparent,
+                        context: context,
+                        builder: (_) => const CoinSelectSheet(),
+                      ).then((value) {
+                        if (value is Coin) {
+                          ref.read(addressEntryDataProvider(widget.id)).coin =
+                              value;
+                        }
+                      });
+                    },
+                    child: Row(
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                      children: [
+                        ref.watch(addressEntryDataProvider(widget.id)
+                                    .select((value) => value.coin)) ==
+                                null
+                            ? Text(
+                                "Select cryptocurrency",
+                                style: STextStyles.fieldLabel(context),
+                              )
+                            : Row(
+                                children: [
+                                  SvgPicture.asset(
+                                    Assets.svg.iconFor(
+                                        coin: ref.watch(
+                                            addressEntryDataProvider(widget.id)
+                                                .select(
+                                                    (value) => value.coin))!),
+                                    height: 20,
+                                    width: 20,
+                                  ),
+                                  const SizedBox(
+                                    width: 12,
+                                  ),
+                                  Text(
+                                    ref
+                                        .watch(
+                                            addressEntryDataProvider(widget.id)
+                                                .select((value) => value.coin))!
+                                        .prettyName,
+                                    style: STextStyles.itemSubtitle12(context),
+                                  ),
+                                ],
+                              ),
+                        if (!isDesktop)
+                          SvgPicture.asset(
+                            Assets.svg.chevronDown,
+                            width: 8,
+                            height: 4,
+                            color: Theme.of(context)
+                                .extension<StackColors>()!
+                                .textSubtitle2,
+                          ),
+                      ],
+                    ),
                   ),
                 ),
               ),
             ),
           ),
-        ),
         const SizedBox(
           height: 8,
         ),
@@ -253,9 +351,10 @@ class _NewContactAddressEntryFormState
                         },
                         child: const ClipboardIcon(),
                       ),
-                    if (!Util.isDesktop && ref.watch(addressEntryDataProvider(widget.id)
-                            .select((value) => value.address)) ==
-                        null)
+                    if (!Util.isDesktop &&
+                        ref.watch(addressEntryDataProvider(widget.id)
+                                .select((value) => value.address)) ==
+                            null)
                       TextFieldIconButton(
                         key: const Key("addAddressBookEntryScanQrButtonKey"),
                         onTap: () async {

From 8799a9cfa2a993379e34a91cef9427b4fe272740 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 15:34:48 -0600
Subject: [PATCH 020/100] my stack contact tweaks

---
 .../subviews/add_address_book_entry_view.dart  |  2 +-
 .../subwidgets/desktop_address_card.dart       | 18 +++++++++++-------
 .../subwidgets/desktop_contact_details.dart    | 11 +++++++----
 3 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart
index bb93c68d8..2759e9cb1 100644
--- a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart
+++ b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart
@@ -559,7 +559,7 @@ class _AddAddressBookEntryViewState
                                   ),
                                 ],
                               ),
-                        if (!isDesktop) const SizedBox(height: 8),
+                        const SizedBox(height: 8),
                         if (forms.length <= 1)
                           const SizedBox(
                             height: 8,
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
index 49b75a4a8..405b9107c 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
@@ -11,9 +11,11 @@ class DesktopAddressCard extends StatelessWidget {
   const DesktopAddressCard({
     Key? key,
     required this.entry,
+    required this.contactId,
   }) : super(key: key);
 
   final ContactAddressEntry entry;
+  final String contactId;
 
   @override
   Widget build(BuildContext context) {
@@ -57,13 +59,15 @@ class DesktopAddressCard extends StatelessWidget {
                     text: "Copy",
                     onTap: () {},
                   ),
-                  const SizedBox(
-                    width: 16,
-                  ),
-                  BlueTextButton(
-                    text: "Edit",
-                    onTap: () {},
-                  ),
+                  if (contactId != "default")
+                    const SizedBox(
+                      width: 16,
+                    ),
+                  if (contactId != "default")
+                    BlueTextButton(
+                      text: "Edit",
+                      onTap: () {},
+                    ),
                 ],
               )
             ],
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
index bc19fe3bd..ada330a14 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
@@ -40,16 +40,18 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
                   width: 32,
                   height: 32,
                   decoration: BoxDecoration(
-                    color: Theme.of(context)
-                        .extension<StackColors>()!
-                        .textFieldDefaultBG,
+                    color: contact.id == "default"
+                        ? Colors.transparent
+                        : Theme.of(context)
+                            .extension<StackColors>()!
+                            .textFieldDefaultBG,
                     borderRadius: BorderRadius.circular(32),
                   ),
                   child: contact.id == "default"
                       ? Center(
                           child: SvgPicture.asset(
                             Assets.svg.stackIcon(context),
-                            width: 20,
+                            width: 32,
                           ),
                         )
                       : contact.emojiChar != null
@@ -134,6 +136,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
                                       padding: const EdgeInsets.all(18),
                                       child: DesktopAddressCard(
                                         entry: contact.addresses[i],
+                                        contactId: contact.id,
                                       ),
                                     ),
                                   ],

From 51c98f90e94d9bbdeb8fe75828ec8f3a848ece29 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 16:01:11 -0600
Subject: [PATCH 021/100] contact tx history

---
 .../desktop_address_book.dart                 |   7 +-
 .../desktop_address_book_scaffold.dart        |   3 +-
 .../subwidgets/desktop_address_card.dart      |  18 +-
 .../subwidgets/desktop_contact_details.dart   | 334 ++++++++++++------
 4 files changed, 248 insertions(+), 114 deletions(-)

diff --git a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
index fd25617e7..f028a3424 100644
--- a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
@@ -427,11 +427,8 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
                 ),
           details: currentContactId == null
               ? Container()
-              : RoundedWhiteContainer(
-            padding: const EdgeInsets.all(24),
-                  child: DesktopContactDetails(
-                    contactId: currentContactId!,
-                  ),
+              : DesktopContactDetails(
+                  contactId: currentContactId!,
                 ),
         ),
       ),
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_book_scaffold.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_book_scaffold.dart
index f32ea1f7f..36e44e6d4 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_book_scaffold.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_book_scaffold.dart
@@ -56,6 +56,7 @@ class DesktopAddressBookScaffold extends StatelessWidget {
         ),
         Expanded(
           child: Row(
+            crossAxisAlignment: CrossAxisAlignment.start,
             children: [
               Expanded(
                 flex: 6,
@@ -96,7 +97,7 @@ class DesktopAddressBookScaffold extends StatelessWidget {
                     const SizedBox(
                       height: weirdRowHeight,
                     ),
-                    Expanded(
+                    Flexible(
                       child: details ?? Container(),
                     ),
                   ],
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
index 405b9107c..f00e0c137 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
@@ -1,8 +1,12 @@
 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 import 'package:stackwallet/models/contact_address_entry.dart';
+import 'package:stackwallet/notifications/show_flush_bar.dart';
 import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/clipboard_interface.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
+import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
@@ -12,10 +16,12 @@ class DesktopAddressCard extends StatelessWidget {
     Key? key,
     required this.entry,
     required this.contactId,
+    this.clipboard = const ClipboardWrapper(),
   }) : super(key: key);
 
   final ContactAddressEntry entry;
   final String contactId;
+  final ClipboardInterface clipboard;
 
   @override
   Widget build(BuildContext context) {
@@ -57,7 +63,17 @@ class DesktopAddressCard extends StatelessWidget {
                 children: [
                   BlueTextButton(
                     text: "Copy",
-                    onTap: () {},
+                    onTap: () {
+                      clipboard.setData(
+                        ClipboardData(text: entry.address),
+                      );
+                      showFloatingFlushBar(
+                        type: FlushBarType.info,
+                        message: "Copied to clipboard",
+                        iconAsset: Assets.svg.copy,
+                        context: context,
+                      );
+                    },
                   ),
                   if (contactId != "default")
                     const SizedBox(
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
index ada330a14..53597826c 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
@@ -1,14 +1,21 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
+import 'package:stackwallet/models/contact.dart';
+import 'package:stackwallet/models/paymint/transactions_model.dart';
 import 'package:stackwallet/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart';
 import 'package:stackwallet/providers/global/address_book_service_provider.dart';
+import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/services/coins/manager.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
+import 'package:stackwallet/widgets/transaction_card.dart';
+import 'package:tuple/tuple.dart';
 
 class DesktopContactDetails extends ConsumerStatefulWidget {
   const DesktopContactDetails({
@@ -24,132 +31,245 @@ class DesktopContactDetails extends ConsumerStatefulWidget {
 }
 
 class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
+  List<Tuple2<String, Transaction>> _cachedTransactions = [];
+
+  bool _contactHasAddress(String address, Contact contact) {
+    for (final entry in contact.addresses) {
+      if (entry.address == address) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  Future<List<Tuple2<String, Transaction>>> _filteredTransactionsByContact(
+    List<Manager> managers,
+  ) async {
+    final contact =
+        ref.read(addressBookServiceProvider).getContactById(widget.contactId);
+
+    // TODO: optimise
+
+    List<Tuple2<String, Transaction>> result = [];
+    for (final manager in managers) {
+      final transactions = (await manager.transactionData)
+          .getAllTransactions()
+          .values
+          .toList()
+          .where((e) => _contactHasAddress(e.address, contact));
+
+      for (final tx in transactions) {
+        result.add(Tuple2(manager.walletId, tx));
+      }
+    }
+    // sort by date
+    result.sort((a, b) => b.item2.timestamp - a.item2.timestamp);
+
+    return result;
+  }
+
   @override
   Widget build(BuildContext context) {
     final contact = ref.watch(addressBookServiceProvider
         .select((value) => value.getContactById(widget.contactId)));
 
-    return Column(
+    return Row(
+      crossAxisAlignment: CrossAxisAlignment.start,
       children: [
-        Row(
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          children: [
-            Row(
-              children: [
-                Container(
-                  width: 32,
-                  height: 32,
-                  decoration: BoxDecoration(
-                    color: contact.id == "default"
-                        ? Colors.transparent
-                        : Theme.of(context)
-                            .extension<StackColors>()!
-                            .textFieldDefaultBG,
-                    borderRadius: BorderRadius.circular(32),
-                  ),
-                  child: contact.id == "default"
-                      ? Center(
-                          child: SvgPicture.asset(
-                            Assets.svg.stackIcon(context),
-                            width: 32,
-                          ),
-                        )
-                      : contact.emojiChar != null
-                          ? Center(
-                              child: Text(contact.emojiChar!),
-                            )
-                          : Center(
-                              child: SvgPicture.asset(
-                                Assets.svg.user,
-                                width: 18,
-                              ),
-                            ),
-                ),
-                const SizedBox(
-                  width: 16,
-                ),
-                Text(
-                  contact.name,
-                  style: STextStyles.desktopTextSmall(context),
-                ),
-              ],
-            ),
-            SecondaryButton(
-              label: "Options",
-              width: 86,
-              buttonHeight: ButtonHeight.xxs,
-              onPressed: () {},
-            ),
-          ],
-        ),
-        const SizedBox(
-          height: 24,
-        ),
         Expanded(
-          child: LayoutBuilder(
-            builder: (context, constraints) {
-              return SingleChildScrollView(
-                child: ConstrainedBox(
-                  constraints: BoxConstraints(
-                    minHeight: constraints.maxHeight,
-                  ),
-                  child: IntrinsicHeight(
-                    child: Column(
+          child: RoundedWhiteContainer(
+            padding: const EdgeInsets.all(24),
+            child: Column(
+              mainAxisSize: MainAxisSize.min,
+              children: [
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  children: [
+                    Row(
                       children: [
-                        Row(
-                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                          children: [
-                            Text(
-                              "Addresses",
-                              style: STextStyles.desktopTextExtraExtraSmall(
-                                  context),
-                            ),
-                            BlueTextButton(
-                              text: "Add new",
-                              onTap: () {},
-                            ),
-                          ],
+                        Container(
+                          width: 32,
+                          height: 32,
+                          decoration: BoxDecoration(
+                            color: contact.id == "default"
+                                ? Colors.transparent
+                                : Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textFieldDefaultBG,
+                            borderRadius: BorderRadius.circular(32),
+                          ),
+                          child: contact.id == "default"
+                              ? Center(
+                                  child: SvgPicture.asset(
+                                    Assets.svg.stackIcon(context),
+                                    width: 32,
+                                  ),
+                                )
+                              : contact.emojiChar != null
+                                  ? Center(
+                                      child: Text(contact.emojiChar!),
+                                    )
+                                  : Center(
+                                      child: SvgPicture.asset(
+                                        Assets.svg.user,
+                                        width: 18,
+                                      ),
+                                    ),
                         ),
                         const SizedBox(
-                          height: 12,
+                          width: 16,
                         ),
-                        RoundedWhiteContainer(
-                          padding: const EdgeInsets.all(0),
-                          borderColor: Theme.of(context)
-                              .extension<StackColors>()!
-                              .background,
-                          child: Column(
-                            mainAxisSize: MainAxisSize.min,
-                            children: [
-                              for (int i = 0; i < contact.addresses.length; i++)
-                                Column(
+                        Text(
+                          contact.name,
+                          style: STextStyles.desktopTextSmall(context),
+                        ),
+                      ],
+                    ),
+                    SecondaryButton(
+                      label: "Options",
+                      width: 86,
+                      buttonHeight: ButtonHeight.xxs,
+                      onPressed: () {},
+                    ),
+                  ],
+                ),
+                const SizedBox(
+                  height: 24,
+                ),
+                Flexible(
+                  child: ListView(
+                    primary: false,
+                    shrinkWrap: true,
+                    // child: Column(
+                    //   crossAxisAlignment: CrossAxisAlignment.start,
+                    //   mainAxisSize: MainAxisSize.min,
+                    children: [
+                      Row(
+                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                        children: [
+                          Text(
+                            "Addresses",
+                            style:
+                                STextStyles.desktopTextExtraExtraSmall(context),
+                          ),
+                          BlueTextButton(
+                            text: "Add new",
+                            onTap: () {},
+                          ),
+                        ],
+                      ),
+                      const SizedBox(
+                        height: 12,
+                      ),
+                      RoundedWhiteContainer(
+                        padding: const EdgeInsets.all(0),
+                        borderColor: Theme.of(context)
+                            .extension<StackColors>()!
+                            .background,
+                        child: Column(
+                          mainAxisSize: MainAxisSize.min,
+                          children: [
+                            for (int i = 0; i < contact.addresses.length; i++)
+                              Column(
+                                mainAxisSize: MainAxisSize.min,
+                                children: [
+                                  if (i > 0)
+                                    Container(
+                                      color: Theme.of(context)
+                                          .extension<StackColors>()!
+                                          .background,
+                                      height: 1,
+                                    ),
+                                  Padding(
+                                    padding: const EdgeInsets.all(18),
+                                    child: DesktopAddressCard(
+                                      entry: contact.addresses[i],
+                                      contactId: contact.id,
+                                    ),
+                                  ),
+                                ],
+                              ),
+                          ],
+                        ),
+                      ),
+                      Text(
+                        "Transaction history",
+                        style: STextStyles.desktopTextExtraExtraSmall(context),
+                      ),
+                      FutureBuilder(
+                        future: _filteredTransactionsByContact(
+                            ref.watch(walletsChangeNotifierProvider).managers),
+                        builder: (_,
+                            AsyncSnapshot<List<Tuple2<String, Transaction>>>
+                                snapshot) {
+                          if (snapshot.connectionState ==
+                                  ConnectionState.done &&
+                              snapshot.hasData) {
+                            _cachedTransactions = snapshot.data!;
+
+                            if (_cachedTransactions.isNotEmpty) {
+                              return RoundedWhiteContainer(
+                                padding: const EdgeInsets.all(0),
+                                borderColor: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .background,
+                                child: Column(
                                   mainAxisSize: MainAxisSize.min,
                                   children: [
-                                    if (i > 0)
-                                      Container(
-                                        color: Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .background,
-                                        height: 1,
-                                      ),
-                                    Padding(
-                                      padding: const EdgeInsets.all(18),
-                                      child: DesktopAddressCard(
-                                        entry: contact.addresses[i],
-                                        contactId: contact.id,
+                                    ..._cachedTransactions.map(
+                                      (e) => TransactionCard(
+                                        key: Key(
+                                            "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey"),
+                                        transaction: e.item2,
+                                        walletId: e.item1,
                                       ),
                                     ),
                                   ],
                                 ),
-                            ],
-                          ),
-                        )
-                      ],
-                    ),
+                              );
+                            } else {
+                              return RoundedWhiteContainer(
+                                child: Center(
+                                  child: Text(
+                                    "No transactions found",
+                                    style: STextStyles.itemSubtitle(context),
+                                  ),
+                                ),
+                              );
+                            }
+                          } else {
+                            // TODO: proper loading animation
+                            if (_cachedTransactions.isEmpty) {
+                              return const LoadingIndicator();
+                            } else {
+                              return RoundedWhiteContainer(
+                                padding: const EdgeInsets.all(0),
+                                borderColor: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .background,
+                                child: Column(
+                                  mainAxisSize: MainAxisSize.min,
+                                  children: [
+                                    ..._cachedTransactions.map(
+                                      (e) => TransactionCard(
+                                        key: Key(
+                                            "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey"),
+                                        transaction: e.item2,
+                                        walletId: e.item1,
+                                      ),
+                                    ),
+                                  ],
+                                ),
+                              );
+                            }
+                          }
+                        },
+                      ),
+                    ],
                   ),
                 ),
-              );
-            },
+              ],
+            ),
           ),
         ),
       ],

From 494849364317cb55e46e8c7e40d786dc37ede959 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 16:18:00 -0600
Subject: [PATCH 022/100] contact tx history

---
 .../subwidgets/desktop_contact_details.dart         | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
index 53597826c..fb094d766 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
@@ -192,9 +192,16 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
                           ],
                         ),
                       ),
-                      Text(
-                        "Transaction history",
-                        style: STextStyles.desktopTextExtraExtraSmall(context),
+                      Padding(
+                        padding: const EdgeInsets.only(
+                          top: 20,
+                          bottom: 12,
+                        ),
+                        child: Text(
+                          "Transaction history",
+                          style:
+                              STextStyles.desktopTextExtraExtraSmall(context),
+                        ),
                       ),
                       FutureBuilder(
                         future: _filteredTransactionsByContact(

From 318758f76850a471ce0dbfc0a1ecd6a190fb4e4a Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Thu, 17 Nov 2022 16:55:34 -0700
Subject: [PATCH 023/100] copy receive address has pointer finger cursor

---
 .../sub_widgets/desktop_receive.dart          | 142 +++++++++---------
 1 file changed, 73 insertions(+), 69 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart
index 3de4ed1e3..1dd2e607e 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart
@@ -117,78 +117,82 @@ class _DesktopReceiveState extends ConsumerState<DesktopReceive> {
     return Column(
       crossAxisAlignment: CrossAxisAlignment.stretch,
       children: [
-        GestureDetector(
-          onTap: () {
-            clipboard.setData(
-              ClipboardData(text: receivingAddress),
-            );
-            showFloatingFlushBar(
-              type: FlushBarType.info,
-              message: "Copied to clipboard",
-              iconAsset: Assets.svg.copy,
-              context: context,
-            );
-          },
-          child: Container(
-            decoration: BoxDecoration(
-              border: Border.all(
-                color: Theme.of(context).extension<StackColors>()!.background,
-                width: 2,
+        MouseRegion(
+          cursor: SystemMouseCursors.click,
+          child: GestureDetector(
+            onTap: () {
+              clipboard.setData(
+                ClipboardData(text: receivingAddress),
+              );
+              showFloatingFlushBar(
+                type: FlushBarType.info,
+                message: "Copied to clipboard",
+                iconAsset: Assets.svg.copy,
+                context: context,
+              );
+            },
+            child: Container(
+              decoration: BoxDecoration(
+                border: Border.all(
+                  color: Theme.of(context).extension<StackColors>()!.background,
+                  width: 2,
+                ),
+                borderRadius: BorderRadius.circular(
+                  Constants.size.circularBorderRadius,
+                ),
               ),
-              borderRadius: BorderRadius.circular(
-                Constants.size.circularBorderRadius,
-              ),
-            ),
-            child: RoundedWhiteContainer(
-              child: Column(
-                children: [
-                  Row(
-                    children: [
-                      Text(
-                        "Your ${coin.ticker} address",
-                        style: STextStyles.itemSubtitle(context),
-                      ),
-                      const Spacer(),
-                      Row(
-                        children: [
-                          SvgPicture.asset(
-                            Assets.svg.copy,
-                            width: 15,
-                            height: 15,
-                            color: Theme.of(context)
-                                .extension<StackColors>()!
-                                .infoItemIcons,
-                          ),
-                          const SizedBox(
-                            width: 4,
-                          ),
-                          Text(
-                            "Copy",
-                            style: STextStyles.link2(context),
-                          ),
-                        ],
-                      ),
-                    ],
-                  ),
-                  const SizedBox(
-                    height: 8,
-                  ),
-                  Row(
-                    children: [
-                      Expanded(
-                        child: Text(
-                          receivingAddress,
-                          style: STextStyles.desktopTextExtraExtraSmall(context)
-                              .copyWith(
-                            color: Theme.of(context)
-                                .extension<StackColors>()!
-                                .textDark,
+              child: RoundedWhiteContainer(
+                child: Column(
+                  children: [
+                    Row(
+                      children: [
+                        Text(
+                          "Your ${coin.ticker} address",
+                          style: STextStyles.itemSubtitle(context),
+                        ),
+                        const Spacer(),
+                        Row(
+                          children: [
+                            SvgPicture.asset(
+                              Assets.svg.copy,
+                              width: 15,
+                              height: 15,
+                              color: Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .infoItemIcons,
+                            ),
+                            const SizedBox(
+                              width: 4,
+                            ),
+                            Text(
+                              "Copy",
+                              style: STextStyles.link2(context),
+                            ),
+                          ],
+                        ),
+                      ],
+                    ),
+                    const SizedBox(
+                      height: 8,
+                    ),
+                    Row(
+                      children: [
+                        Expanded(
+                          child: Text(
+                            receivingAddress,
+                            style:
+                                STextStyles.desktopTextExtraExtraSmall(context)
+                                    .copyWith(
+                              color: Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textDark,
+                            ),
                           ),
                         ),
-                      ),
-                    ],
-                  ),
-                ],
+                      ],
+                    ),
+                  ],
+                ),
               ),
             ),
           ),

From cd19d776ae04631571a8d64b008d3cf52746d331 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 16:47:50 -0600
Subject: [PATCH 024/100] desktop edit contact address entry

---
 .../subviews/edit_contact_address_view.dart   | 433 +++++++++---------
 .../subwidgets/desktop_address_card.dart      |  62 ++-
 2 files changed, 268 insertions(+), 227 deletions(-)

diff --git a/lib/pages/address_book_views/subviews/edit_contact_address_view.dart b/lib/pages/address_book_views/subviews/edit_contact_address_view.dart
index 618a41982..f0143d39d 100644
--- a/lib/pages/address_book_views/subviews/edit_contact_address_view.dart
+++ b/lib/pages/address_book_views/subviews/edit_contact_address_view.dart
@@ -12,7 +12,11 @@ import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
 import 'package:stackwallet/utilities/clipboard_interface.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 
 class EditContactAddressView extends ConsumerStatefulWidget {
   const EditContactAddressView({
@@ -44,6 +48,42 @@ class _EditContactAddressViewState
   late final BarcodeScannerInterface barcodeScanner;
   late final ClipboardInterface clipboard;
 
+  Future<void> save(Contact contact) async {
+    if (FocusScope.of(context).hasFocus) {
+      FocusScope.of(context).unfocus();
+      await Future<void>.delayed(
+        const Duration(milliseconds: 75),
+      );
+    }
+    List<ContactAddressEntry> entries = contact.addresses.toList();
+
+    final entry = entries.firstWhere(
+      (e) =>
+          e.label == addressEntry.label &&
+          e.address == addressEntry.address &&
+          e.coin == addressEntry.coin,
+    );
+
+    final index = entries.indexOf(entry);
+    entries.remove(entry);
+
+    ContactAddressEntry editedEntry =
+        ref.read(addressEntryDataProvider(0)).buildAddressEntry();
+
+    entries.insert(index, editedEntry);
+
+    Contact editedContact = contact.copyWith(addresses: entries);
+
+    if (await ref.read(addressBookServiceProvider).editContact(editedContact)) {
+      if (mounted) {
+        Navigator.of(context).pop();
+      }
+      // TODO show success notification
+    } else {
+      // TODO show error notification
+    }
+  }
+
   @override
   void initState() {
     contactId = widget.contactId;
@@ -59,236 +99,181 @@ class _EditContactAddressViewState
     final contact = ref.watch(addressBookServiceProvider
         .select((value) => value.getContactById(contactId)));
 
-    return Scaffold(
-      backgroundColor: Theme.of(context).extension<StackColors>()!.background,
-      appBar: AppBar(
-        leading: AppBarBackButton(
-          onPressed: () async {
-            if (FocusScope.of(context).hasFocus) {
-              FocusScope.of(context).unfocus();
-              await Future<void>.delayed(const Duration(milliseconds: 75));
-            }
-            if (mounted) {
-              Navigator.of(context).pop();
-            }
-          },
+    final bool isDesktop = Util.isDesktop;
+
+    return ConditionalParent(
+      condition: !isDesktop,
+      builder: (child) => Scaffold(
+        backgroundColor: Theme.of(context).extension<StackColors>()!.background,
+        appBar: AppBar(
+          leading: AppBarBackButton(
+            onPressed: () async {
+              if (FocusScope.of(context).hasFocus) {
+                FocusScope.of(context).unfocus();
+                await Future<void>.delayed(const Duration(milliseconds: 75));
+              }
+              if (mounted) {
+                Navigator.of(context).pop();
+              }
+            },
+          ),
+          title: Text(
+            "Edit address",
+            style: STextStyles.navBarTitle(context),
+          ),
         ),
-        title: Text(
-          "Edit address",
-          style: STextStyles.navBarTitle(context),
-        ),
-      ),
-      body: LayoutBuilder(
-        builder: (context, constraints) {
-          return Padding(
-            padding: const EdgeInsets.only(
-              left: 12,
-              top: 12,
-              right: 12,
-            ),
-            child: SingleChildScrollView(
-              child: ConstrainedBox(
-                constraints: BoxConstraints(
-                  minHeight: constraints.maxHeight - 24,
-                ),
-                child: IntrinsicHeight(
-                  child: Padding(
-                    padding: const EdgeInsets.all(4),
-                    child: Column(
-                      children: [
-                        Row(
-                          children: [
-                            Container(
-                              height: 48,
-                              width: 48,
-                              decoration: BoxDecoration(
-                                borderRadius: BorderRadius.circular(24),
-                                color: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .textFieldActiveBG,
-                              ),
-                              child: Center(
-                                child: contact.emojiChar == null
-                                    ? SvgPicture.asset(
-                                        Assets.svg.user,
-                                        height: 24,
-                                        width: 24,
-                                      )
-                                    : Text(
-                                        contact.emojiChar!,
-                                        style: STextStyles.pageTitleH1(context),
-                                      ),
-                              ),
-                            ),
-                            const SizedBox(
-                              width: 16,
-                            ),
-                            Expanded(
-                              child: FittedBox(
-                                fit: BoxFit.scaleDown,
-                                child: Text(
-                                  contact.name,
-                                  style: STextStyles.pageTitleH2(context),
-                                ),
-                              ),
-                            ),
-                          ],
-                        ),
-                        const SizedBox(
-                          height: 16,
-                        ),
-                        NewContactAddressEntryForm(
-                          id: 0,
-                          barcodeScanner: barcodeScanner,
-                          clipboard: clipboard,
-                        ),
-                        const SizedBox(
-                          height: 24,
-                        ),
-                        GestureDetector(
-                          onTap: () async {
-                            // delete address
-                            final _addresses = contact.addresses;
-                            final entry = _addresses.firstWhere(
-                              (e) =>
-                                  e.label == addressEntry.label &&
-                                  e.address == addressEntry.address &&
-                                  e.coin == addressEntry.coin,
-                            );
-
-                            _addresses.remove(entry);
-                            Contact editedContact =
-                                contact.copyWith(addresses: _addresses);
-                            if (await ref
-                                .read(addressBookServiceProvider)
-                                .editContact(editedContact)) {
-                              Navigator.of(context).pop();
-                              // TODO show success notification
-                            } else {
-                              // TODO show error notification
-                            }
-                          },
-                          child: Text(
-                            "Delete address",
-                            style: STextStyles.link(context),
-                          ),
-                        ),
-                        const Spacer(),
-                        const SizedBox(
-                          height: 16,
-                        ),
-                        Row(
-                          children: [
-                            Expanded(
-                              child: TextButton(
-                                style: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .getSecondaryEnabledButtonColor(context),
-                                child: Text(
-                                  "Cancel",
-                                  style: STextStyles.button(context).copyWith(
-                                      color: Theme.of(context)
-                                          .extension<StackColors>()!
-                                          .accentColorDark),
-                                ),
-                                onPressed: () async {
-                                  if (FocusScope.of(context).hasFocus) {
-                                    FocusScope.of(context).unfocus();
-                                    await Future<void>.delayed(
-                                        const Duration(milliseconds: 75));
-                                  }
-                                  if (mounted) {
-                                    Navigator.of(context).pop();
-                                  }
-                                },
-                              ),
-                            ),
-                            const SizedBox(
-                              width: 16,
-                            ),
-                            Expanded(
-                              child: Builder(
-                                builder: (context) {
-                                  bool shouldEnableSave =
-                                      ref.watch(validContactStateProvider([0]));
-
-                                  return TextButton(
-                                    style: shouldEnableSave
-                                        ? Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .getPrimaryEnabledButtonColor(
-                                                context)
-                                        : Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .getPrimaryDisabledButtonColor(
-                                                context),
-                                    onPressed: shouldEnableSave
-                                        ? () async {
-                                            if (FocusScope.of(context)
-                                                .hasFocus) {
-                                              FocusScope.of(context).unfocus();
-                                              await Future<void>.delayed(
-                                                const Duration(
-                                                    milliseconds: 75),
-                                              );
-                                            }
-                                            List<ContactAddressEntry> entries =
-                                                contact.addresses.toList();
-
-                                            final entry = entries.firstWhere(
-                                              (e) =>
-                                                  e.label ==
-                                                      addressEntry.label &&
-                                                  e.address ==
-                                                      addressEntry.address &&
-                                                  e.coin == addressEntry.coin,
-                                            );
-
-                                            final index =
-                                                entries.indexOf(entry);
-                                            entries.remove(entry);
-
-                                            ContactAddressEntry editedEntry = ref
-                                                .read(
-                                                    addressEntryDataProvider(0))
-                                                .buildAddressEntry();
-
-                                            entries.insert(index, editedEntry);
-
-                                            Contact editedContact = contact
-                                                .copyWith(addresses: entries);
-
-                                            if (await ref
-                                                .read(
-                                                    addressBookServiceProvider)
-                                                .editContact(editedContact)) {
-                                              if (mounted) {
-                                                Navigator.of(context).pop();
-                                              }
-                                              // TODO show success notification
-                                            } else {
-                                              // TODO show error notification
-                                            }
-                                          }
-                                        : null,
-                                    child: Text(
-                                      "Save",
-                                      style: STextStyles.button(context),
-                                    ),
-                                  );
-                                },
-                              ),
-                            ),
-                          ],
-                        ),
-                      ],
+        body: LayoutBuilder(
+          builder: (context, constraints) {
+            return Padding(
+              padding: const EdgeInsets.only(
+                left: 12,
+                top: 12,
+                right: 12,
+              ),
+              child: SingleChildScrollView(
+                child: ConstrainedBox(
+                  constraints: BoxConstraints(
+                    minHeight: constraints.maxHeight - 24,
+                  ),
+                  child: IntrinsicHeight(
+                    child: Padding(
+                      padding: const EdgeInsets.all(4),
+                      child: child,
                     ),
                   ),
                 ),
               ),
+            );
+          },
+        ),
+      ),
+      child: Column(
+        children: [
+          Row(
+            children: [
+              Container(
+                height: 48,
+                width: 48,
+                decoration: BoxDecoration(
+                  borderRadius: BorderRadius.circular(24),
+                  color: Theme.of(context)
+                      .extension<StackColors>()!
+                      .textFieldActiveBG,
+                ),
+                child: Center(
+                  child: contact.emojiChar == null
+                      ? SvgPicture.asset(
+                          Assets.svg.user,
+                          height: 24,
+                          width: 24,
+                        )
+                      : Text(
+                          contact.emojiChar!,
+                          style: STextStyles.pageTitleH1(context),
+                        ),
+                ),
+              ),
+              const SizedBox(
+                width: 16,
+              ),
+              if (isDesktop)
+                Text(
+                  contact.name,
+                  style: STextStyles.pageTitleH2(context),
+                ),
+              if (!isDesktop)
+                Expanded(
+                  child: FittedBox(
+                    fit: BoxFit.scaleDown,
+                    child: Text(
+                      contact.name,
+                      style: STextStyles.pageTitleH2(context),
+                    ),
+                  ),
+                ),
+            ],
+          ),
+          const SizedBox(
+            height: 16,
+          ),
+          NewContactAddressEntryForm(
+            id: 0,
+            barcodeScanner: barcodeScanner,
+            clipboard: clipboard,
+          ),
+          const SizedBox(
+            height: 24,
+          ),
+          ConditionalParent(
+            condition: isDesktop,
+            builder: (child) => MouseRegion(
+              cursor: SystemMouseCursors.click,
+              child: child,
             ),
-          );
-        },
+            child: GestureDetector(
+              onTap: () async {
+                // delete address
+                final _addresses = contact.addresses;
+                final entry = _addresses.firstWhere(
+                  (e) =>
+                      e.label == addressEntry.label &&
+                      e.address == addressEntry.address &&
+                      e.coin == addressEntry.coin,
+                );
+
+                _addresses.remove(entry);
+                Contact editedContact = contact.copyWith(addresses: _addresses);
+                if (await ref
+                    .read(addressBookServiceProvider)
+                    .editContact(editedContact)) {
+                  Navigator.of(context).pop();
+                  // TODO show success notification
+                } else {
+                  // TODO show error notification
+                }
+              },
+              child: Text(
+                "Delete address",
+                style: STextStyles.link(context),
+              ),
+            ),
+          ),
+          const Spacer(),
+          const SizedBox(
+            height: 16,
+          ),
+          Row(
+            children: [
+              Expanded(
+                child: SecondaryButton(
+                  label: "Cancel",
+                  buttonHeight: isDesktop ? ButtonHeight.l : null,
+                  onPressed: () async {
+                    if (!isDesktop && FocusScope.of(context).hasFocus) {
+                      FocusScope.of(context).unfocus();
+                      await Future<void>.delayed(
+                          const Duration(milliseconds: 75));
+                    }
+                    if (mounted) {
+                      Navigator.of(context).pop();
+                    }
+                  },
+                ),
+              ),
+              const SizedBox(
+                width: 16,
+              ),
+              Expanded(
+                child: PrimaryButton(
+                  label: "Save",
+                  enabled: ref.watch(validContactStateProvider([0])),
+                  onPressed: () => save(contact),
+                  buttonHeight: isDesktop ? ButtonHeight.l : null,
+                ),
+              ),
+            ],
+          ),
+        ],
       ),
     );
   }
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
index f00e0c137..713c9e965 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
@@ -1,15 +1,20 @@
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 import 'package:stackwallet/models/contact_address_entry.dart';
 import 'package:stackwallet/notifications/show_flush_bar.dart';
+import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
+import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/clipboard_interface.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 
 class DesktopAddressCard extends StatelessWidget {
   const DesktopAddressCard({
@@ -80,9 +85,60 @@ class DesktopAddressCard extends StatelessWidget {
                       width: 16,
                     ),
                   if (contactId != "default")
-                    BlueTextButton(
-                      text: "Edit",
-                      onTap: () {},
+                    Consumer(
+                      builder: (context, ref, child) {
+                        return BlueTextButton(
+                          text: "Edit",
+                          onTap: () async {
+                            ref.read(addressEntryDataProvider(0)).address =
+                                entry.address;
+                            ref.read(addressEntryDataProvider(0)).addressLabel =
+                                entry.label;
+                            ref.read(addressEntryDataProvider(0)).coin =
+                                entry.coin;
+
+                            await showDialog<void>(
+                              context: context,
+                              builder: (context) => DesktopDialog(
+                                maxWidth: 580,
+                                maxHeight: 566,
+                                child: Column(
+                                  children: [
+                                    Row(
+                                      children: [
+                                        const SizedBox(
+                                          width: 8,
+                                        ),
+                                        const AppBarBackButton(
+                                          isCompact: true,
+                                        ),
+                                        Text(
+                                          "Edit address",
+                                          style: STextStyles.desktopH3(context),
+                                        ),
+                                      ],
+                                    ),
+                                    Expanded(
+                                      child: Padding(
+                                        padding: const EdgeInsets.only(
+                                          top: 20,
+                                          left: 32,
+                                          right: 32,
+                                          bottom: 32,
+                                        ),
+                                        child: EditContactAddressView(
+                                          contactId: contactId,
+                                          addressEntry: entry,
+                                        ),
+                                      ),
+                                    ),
+                                  ],
+                                ),
+                              ),
+                            );
+                          },
+                        );
+                      },
                     ),
                 ],
               )

From df64e48e1ef2985cc58363bf844c288bd71ebd5a Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 17:00:06 -0600
Subject: [PATCH 025/100] desktop add new contact address entry

---
 .../add_new_contact_address_view.dart         | 342 +++++++++---------
 .../subwidgets/desktop_address_card.dart      |   2 +
 .../subwidgets/desktop_contact_details.dart   |  49 ++-
 3 files changed, 213 insertions(+), 180 deletions(-)

diff --git a/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart b/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart
index e5dbaa7b9..dc25c3dc1 100644
--- a/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart
+++ b/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart
@@ -12,7 +12,11 @@ import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
 import 'package:stackwallet/utilities/clipboard_interface.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 
 class AddNewContactAddressView extends ConsumerStatefulWidget {
   const AddNewContactAddressView({
@@ -55,190 +59,170 @@ class _AddNewContactAddressViewState
     final contact = ref.watch(addressBookServiceProvider
         .select((value) => value.getContactById(contactId)));
 
-    return Scaffold(
-      backgroundColor: Theme.of(context).extension<StackColors>()!.background,
-      appBar: AppBar(
-        leading: AppBarBackButton(
-          onPressed: () async {
-            if (FocusScope.of(context).hasFocus) {
-              FocusScope.of(context).unfocus();
-              await Future<void>.delayed(const Duration(milliseconds: 75));
-            }
-            if (mounted) {
-              Navigator.of(context).pop();
-            }
-          },
+    final isDesktop = Util.isDesktop;
+
+    return ConditionalParent(
+      condition: !isDesktop,
+      builder: (child) => Scaffold(
+        backgroundColor: Theme.of(context).extension<StackColors>()!.background,
+        appBar: AppBar(
+          leading: AppBarBackButton(
+            onPressed: () async {
+              if (FocusScope.of(context).hasFocus) {
+                FocusScope.of(context).unfocus();
+                await Future<void>.delayed(const Duration(milliseconds: 75));
+              }
+              if (mounted) {
+                Navigator.of(context).pop();
+              }
+            },
+          ),
+          title: Text(
+            "Add new address",
+            style: STextStyles.navBarTitle(context),
+          ),
         ),
-        title: Text(
-          "Add new address",
-          style: STextStyles.navBarTitle(context),
-        ),
-      ),
-      body: LayoutBuilder(
-        builder: (context, constraints) {
-          return Padding(
-            padding: const EdgeInsets.only(
-              left: 12,
-              top: 12,
-              right: 12,
-            ),
-            child: SingleChildScrollView(
-              child: ConstrainedBox(
-                constraints: BoxConstraints(
-                  minHeight: constraints.maxHeight - 24,
-                ),
-                child: IntrinsicHeight(
-                  child: Padding(
-                    padding: const EdgeInsets.all(4),
-                    child: Column(
-                      children: [
-                        Row(
-                          children: [
-                            Container(
-                              height: 48,
-                              width: 48,
-                              decoration: BoxDecoration(
-                                borderRadius: BorderRadius.circular(24),
-                                color: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .textFieldActiveBG,
-                              ),
-                              child: Center(
-                                child: contact.emojiChar == null
-                                    ? SvgPicture.asset(
-                                        Assets.svg.user,
-                                        height: 24,
-                                        width: 24,
-                                      )
-                                    : Text(
-                                        contact.emojiChar!,
-                                        style: STextStyles.pageTitleH1(context),
-                                      ),
-                              ),
-                            ),
-                            const SizedBox(
-                              width: 16,
-                            ),
-                            Expanded(
-                              child: FittedBox(
-                                fit: BoxFit.scaleDown,
-                                child: Text(
-                                  contact.name,
-                                  style: STextStyles.pageTitleH2(context),
-                                ),
-                              ),
-                            ),
-                          ],
-                        ),
-                        const SizedBox(
-                          height: 16,
-                        ),
-                        NewContactAddressEntryForm(
-                          id: 0,
-                          barcodeScanner: barcodeScanner,
-                          clipboard: clipboard,
-                        ),
-                        const SizedBox(
-                          height: 16,
-                        ),
-                        const Spacer(),
-                        Row(
-                          children: [
-                            Expanded(
-                              child: TextButton(
-                                style: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .getSecondaryEnabledButtonColor(context),
-                                child: Text(
-                                  "Cancel",
-                                  style: STextStyles.button(context).copyWith(
-                                      color: Theme.of(context)
-                                          .extension<StackColors>()!
-                                          .accentColorDark),
-                                ),
-                                onPressed: () async {
-                                  if (FocusScope.of(context).hasFocus) {
-                                    FocusScope.of(context).unfocus();
-                                    await Future<void>.delayed(
-                                        const Duration(milliseconds: 75));
-                                  }
-                                  if (mounted) {
-                                    Navigator.of(context).pop();
-                                  }
-                                },
-                              ),
-                            ),
-                            const SizedBox(
-                              width: 16,
-                            ),
-                            Expanded(
-                              child: Builder(
-                                builder: (context) {
-                                  bool shouldEnableSave =
-                                      ref.watch(validContactStateProvider([0]));
-
-                                  return TextButton(
-                                    style: shouldEnableSave
-                                        ? Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .getPrimaryEnabledButtonColor(
-                                                context)
-                                        : Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .getPrimaryDisabledButtonColor(
-                                                context),
-                                    onPressed: shouldEnableSave
-                                        ? () async {
-                                            if (FocusScope.of(context)
-                                                .hasFocus) {
-                                              FocusScope.of(context).unfocus();
-                                              await Future<void>.delayed(
-                                                const Duration(
-                                                    milliseconds: 75),
-                                              );
-                                            }
-                                            List<ContactAddressEntry> entries =
-                                                contact.addresses;
-
-                                            entries.add(ref
-                                                .read(
-                                                    addressEntryDataProvider(0))
-                                                .buildAddressEntry());
-
-                                            Contact editedContact = contact
-                                                .copyWith(addresses: entries);
-
-                                            if (await ref
-                                                .read(
-                                                    addressBookServiceProvider)
-                                                .editContact(editedContact)) {
-                                              if (mounted) {
-                                                Navigator.of(context).pop();
-                                              }
-                                              // TODO show success notification
-                                            } else {
-                                              // TODO show error notification
-                                            }
-                                          }
-                                        : null,
-                                    child: Text(
-                                      "Save",
-                                      style: STextStyles.button(context),
-                                    ),
-                                  );
-                                },
-                              ),
-                            ),
-                          ],
-                        )
-                      ],
+        body: LayoutBuilder(
+          builder: (context, constraints) {
+            return Padding(
+              padding: const EdgeInsets.only(
+                left: 12,
+                top: 12,
+                right: 12,
+              ),
+              child: SingleChildScrollView(
+                child: ConstrainedBox(
+                  constraints: BoxConstraints(
+                    minHeight: constraints.maxHeight - 24,
+                  ),
+                  child: IntrinsicHeight(
+                    child: Padding(
+                      padding: const EdgeInsets.all(4),
+                      child: child,
                     ),
                   ),
                 ),
               ),
-            ),
-          );
-        },
+            );
+          },
+        ),
+      ),
+      child: Column(
+        children: [
+          Row(
+            children: [
+              Container(
+                height: 48,
+                width: 48,
+                decoration: BoxDecoration(
+                  borderRadius: BorderRadius.circular(24),
+                  color: Theme.of(context)
+                      .extension<StackColors>()!
+                      .textFieldActiveBG,
+                ),
+                child: Center(
+                  child: contact.emojiChar == null
+                      ? SvgPicture.asset(
+                          Assets.svg.user,
+                          height: 24,
+                          width: 24,
+                        )
+                      : Text(
+                          contact.emojiChar!,
+                          style: STextStyles.pageTitleH1(context),
+                        ),
+                ),
+              ),
+              const SizedBox(
+                width: 16,
+              ),
+              if (isDesktop)
+                Text(
+                  contact.name,
+                  style: STextStyles.pageTitleH2(context),
+                ),
+              if (!isDesktop)
+                Expanded(
+                  child: FittedBox(
+                    fit: BoxFit.scaleDown,
+                    child: Text(
+                      contact.name,
+                      style: STextStyles.pageTitleH2(context),
+                    ),
+                  ),
+                ),
+            ],
+          ),
+          const SizedBox(
+            height: 16,
+          ),
+          NewContactAddressEntryForm(
+            id: 0,
+            barcodeScanner: barcodeScanner,
+            clipboard: clipboard,
+          ),
+          const SizedBox(
+            height: 16,
+          ),
+          const Spacer(),
+          Row(
+            children: [
+              Expanded(
+                child: SecondaryButton(
+                  label: "Cancel",
+                  buttonHeight: isDesktop ? ButtonHeight.l : null,
+                  onPressed: () async {
+                    if (!isDesktop && FocusScope.of(context).hasFocus) {
+                      FocusScope.of(context).unfocus();
+                      await Future<void>.delayed(
+                          const Duration(milliseconds: 75));
+                    }
+                    if (mounted) {
+                      Navigator.of(context).pop();
+                    }
+                  },
+                ),
+              ),
+              const SizedBox(
+                width: 16,
+              ),
+              Expanded(
+                child: PrimaryButton(
+                  label: "Save",
+                  enabled: ref.watch(validContactStateProvider([0])),
+                  buttonHeight: isDesktop ? ButtonHeight.l : null,
+                  onPressed: () async {
+                    if (FocusScope.of(context).hasFocus) {
+                      FocusScope.of(context).unfocus();
+                      await Future<void>.delayed(
+                        const Duration(milliseconds: 75),
+                      );
+                    }
+                    List<ContactAddressEntry> entries = contact.addresses;
+
+                    entries.add(ref
+                        .read(addressEntryDataProvider(0))
+                        .buildAddressEntry());
+
+                    Contact editedContact =
+                        contact.copyWith(addresses: entries);
+
+                    if (await ref
+                        .read(addressBookServiceProvider)
+                        .editContact(editedContact)) {
+                      if (mounted) {
+                        Navigator.of(context).pop();
+                      }
+                      // TODO show success notification
+                    } else {
+                      // TODO show error notification
+                    }
+                  },
+                ),
+              ),
+            ],
+          )
+        ],
       ),
     );
   }
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
index 713c9e965..4d58dc474 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart
@@ -90,6 +90,8 @@ class DesktopAddressCard extends StatelessWidget {
                         return BlueTextButton(
                           text: "Edit",
                           onTap: () async {
+                            ref.refresh(
+                                addressEntryDataProviderFamilyRefresher);
                             ref.read(addressEntryDataProvider(0)).address =
                                 entry.address;
                             ref.read(addressEntryDataProvider(0)).addressLabel =
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
index fb094d766..1c27b6836 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
@@ -3,14 +3,18 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 import 'package:stackwallet/models/contact.dart';
 import 'package:stackwallet/models/paymint/transactions_model.dart';
+import 'package:stackwallet/pages/address_book_views/subviews/add_new_contact_address_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart';
 import 'package:stackwallet/providers/global/address_book_service_provider.dart';
 import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
 import 'package:stackwallet/services/coins/manager.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
@@ -154,7 +158,50 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
                           ),
                           BlueTextButton(
                             text: "Add new",
-                            onTap: () {},
+                            onTap: () async {
+                              ref.refresh(
+                                  addressEntryDataProviderFamilyRefresher);
+
+                              await showDialog<void>(
+                                context: context,
+                                builder: (context) => DesktopDialog(
+                                  maxWidth: 580,
+                                  maxHeight: 566,
+                                  child: Column(
+                                    children: [
+                                      Row(
+                                        children: [
+                                          const SizedBox(
+                                            width: 8,
+                                          ),
+                                          const AppBarBackButton(
+                                            isCompact: true,
+                                          ),
+                                          Text(
+                                            "Add new address",
+                                            style:
+                                                STextStyles.desktopH3(context),
+                                          ),
+                                        ],
+                                      ),
+                                      Expanded(
+                                        child: Padding(
+                                          padding: const EdgeInsets.only(
+                                            top: 20,
+                                            left: 32,
+                                            right: 32,
+                                            bottom: 32,
+                                          ),
+                                          child: AddNewContactAddressView(
+                                            contactId: widget.contactId,
+                                          ),
+                                        ),
+                                      ),
+                                    ],
+                                  ),
+                                ),
+                              );
+                            },
                           ),
                         ],
                       ),

From e70f5b0709eea46f42cfd4ed8dd9f7ba2aa24b20 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 18:14:30 -0600
Subject: [PATCH 026/100] WIP desktop contact options context popup menu

---
 .../subwidgets/desktop_contact_details.dart   | 262 +++++++++++++++++-
 1 file changed, 260 insertions(+), 2 deletions(-)

diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
index 1c27b6836..2cd20a839 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
@@ -131,9 +131,19 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
                     ),
                     SecondaryButton(
                       label: "Options",
-                      width: 86,
+                      width: 96,
                       buttonHeight: ButtonHeight.xxs,
-                      onPressed: () {},
+                      onPressed: () async {
+                        await showDialog<void>(
+                          context: context,
+                          barrierColor: Colors.transparent,
+                          builder: (context) {
+                            return DesktopContactOptionsMenuPopup(
+                              contactId: contact.id,
+                            );
+                          },
+                        );
+                      },
                     ),
                   ],
                 ),
@@ -330,3 +340,251 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
     );
   }
 }
+
+class DesktopContactOptionsMenuPopup extends ConsumerStatefulWidget {
+  const DesktopContactOptionsMenuPopup({Key? key, required this.contactId})
+      : super(key: key);
+
+  final String contactId;
+
+  @override
+  ConsumerState<DesktopContactOptionsMenuPopup> createState() =>
+      _DesktopContactOptionsMenuPopupState();
+}
+
+class _DesktopContactOptionsMenuPopupState
+    extends ConsumerState<DesktopContactOptionsMenuPopup> {
+  bool hoveredOnStar = false;
+  bool hoveredOnPencil = false;
+  bool hoveredOnTrash = false;
+
+  @override
+  Widget build(BuildContext context) {
+    return Stack(
+      children: [
+        Positioned(
+          top: 210,
+          left: MediaQuery.of(context).size.width - 280,
+          child: Container(
+            width: 270,
+            decoration: BoxDecoration(
+              color: Theme.of(context).extension<StackColors>()!.popupBG,
+              borderRadius: BorderRadius.circular(
+                20,
+              ),
+              boxShadow: [
+                Theme.of(context).extension<StackColors>()!.standardBoxShadow,
+              ],
+            ),
+            child: Padding(
+              padding: const EdgeInsets.all(16),
+              child: Column(
+                children: [
+                  MouseRegion(
+                    onEnter: (_) {
+                      setState(() {
+                        hoveredOnStar = true;
+                      });
+                    },
+                    onExit: (_) {
+                      setState(() {
+                        hoveredOnStar = false;
+                      });
+                    },
+                    child: RawMaterialButton(
+                      hoverColor: Theme.of(context)
+                          .extension<StackColors>()!
+                          .textFieldDefaultBG,
+                      shape: RoundedRectangleBorder(
+                        borderRadius: BorderRadius.circular(
+                          1000,
+                        ),
+                      ),
+                      onPressed: () {
+                        final contact =
+                            ref.read(addressBookServiceProvider).getContactById(
+                                  widget.contactId,
+                                );
+                        ref.read(addressBookServiceProvider).editContact(
+                              contact.copyWith(
+                                isFavorite: !contact.isFavorite,
+                              ),
+                            );
+                      },
+                      child: Padding(
+                        padding: const EdgeInsets.symmetric(
+                          horizontal: 25,
+                          vertical: 16,
+                        ),
+                        child: Row(
+                          children: [
+                            SvgPicture.asset(
+                              Assets.svg.star,
+                              width: 24,
+                              height: 22,
+                              color: hoveredOnStar
+                                  ? Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark
+                                  : Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textFieldDefaultSearchIconLeft,
+                            ),
+                            const SizedBox(
+                              width: 12,
+                            ),
+                            Text(
+                              ref.watch(addressBookServiceProvider.select(
+                                      (value) => value
+                                          .getContactById(widget.contactId)
+                                          .isFavorite))
+                                  ? "Remove from favorites"
+                                  : "Add to favorites",
+                              style: STextStyles.desktopTextExtraExtraSmall(
+                                      context)
+                                  .copyWith(
+                                color: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textDark,
+                              ),
+                            )
+                          ],
+                        ),
+                      ),
+                    ),
+                  ),
+                  const SizedBox(
+                    height: 2,
+                  ),
+                  MouseRegion(
+                    onEnter: (_) {
+                      setState(() {
+                        hoveredOnPencil = true;
+                      });
+                    },
+                    onExit: (_) {
+                      setState(() {
+                        hoveredOnPencil = false;
+                      });
+                    },
+                    child: RawMaterialButton(
+                      hoverColor: Theme.of(context)
+                          .extension<StackColors>()!
+                          .textFieldDefaultBG,
+                      shape: RoundedRectangleBorder(
+                        borderRadius: BorderRadius.circular(
+                          1000,
+                        ),
+                      ),
+                      onPressed: () {
+                        print("should go to edit");
+                      },
+                      child: Padding(
+                        padding: const EdgeInsets.symmetric(
+                          horizontal: 25,
+                          vertical: 16,
+                        ),
+                        child: Row(
+                          children: [
+                            SvgPicture.asset(
+                              Assets.svg.pencil,
+                              width: 24,
+                              height: 22,
+                              color: hoveredOnPencil
+                                  ? Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark
+                                  : Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textFieldDefaultSearchIconLeft,
+                            ),
+                            const SizedBox(
+                              width: 12,
+                            ),
+                            Text(
+                              "Edit contact",
+                              style: STextStyles.desktopTextExtraExtraSmall(
+                                      context)
+                                  .copyWith(
+                                color: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textDark,
+                              ),
+                            )
+                          ],
+                        ),
+                      ),
+                    ),
+                  ),
+                  const SizedBox(
+                    height: 2,
+                  ),
+                  MouseRegion(
+                    onEnter: (_) {
+                      setState(() {
+                        hoveredOnTrash = true;
+                      });
+                    },
+                    onExit: (_) {
+                      setState(() {
+                        hoveredOnTrash = false;
+                      });
+                    },
+                    child: RawMaterialButton(
+                      hoverColor: Theme.of(context)
+                          .extension<StackColors>()!
+                          .textFieldDefaultBG,
+                      shape: RoundedRectangleBorder(
+                        borderRadius: BorderRadius.circular(
+                          1000,
+                        ),
+                      ),
+                      onPressed: () {
+                        print("should delete contact");
+                      },
+                      child: Padding(
+                        padding: const EdgeInsets.symmetric(
+                          horizontal: 25,
+                          vertical: 16,
+                        ),
+                        child: Row(
+                          children: [
+                            SvgPicture.asset(
+                              Assets.svg.trash,
+                              width: 24,
+                              height: 22,
+                              color: hoveredOnTrash
+                                  ? Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark
+                                  : Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textFieldDefaultSearchIconLeft,
+                            ),
+                            const SizedBox(
+                              width: 12,
+                            ),
+                            Text(
+                              "Delete contact",
+                              style: STextStyles.desktopTextExtraExtraSmall(
+                                      context)
+                                  .copyWith(
+                                color: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textDark,
+                              ),
+                            )
+                          ],
+                        ),
+                      ),
+                    ),
+                  ),
+                ],
+              ),
+            ),
+          ),
+        ),
+      ],
+    );
+  }
+}

From 38251dc5edb0d5e2f6a771e53deb98aa0e96a68e Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 18:21:04 -0600
Subject: [PATCH 027/100] textStyles prep for ocean theme

---
 lib/utilities/text_styles.dart       | 54 ++++++++++++++++++++++++++++
 lib/utilities/theme/color_theme.dart |  1 +
 2 files changed, 55 insertions(+)

diff --git a/lib/utilities/text_styles.dart b/lib/utilities/text_styles.dart
index 63aa19afb..db4764459 100644
--- a/lib/utilities/text_styles.dart
+++ b/lib/utilities/text_styles.dart
@@ -15,6 +15,7 @@ class STextStyles {
           fontWeight: FontWeight.w600,
           fontSize: 20,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -32,6 +33,7 @@ class STextStyles {
           fontWeight: FontWeight.w600,
           fontSize: 18,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -49,6 +51,7 @@ class STextStyles {
           fontWeight: FontWeight.w600,
           fontSize: 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -66,6 +69,7 @@ class STextStyles {
           fontWeight: FontWeight.w600,
           fontSize: 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -83,6 +87,7 @@ class STextStyles {
           fontWeight: FontWeight.w400,
           fontSize: 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -100,6 +105,7 @@ class STextStyles {
           fontWeight: FontWeight.w400,
           fontSize: 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -117,6 +123,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -134,6 +141,7 @@ class STextStyles {
           fontWeight: FontWeight.w600,
           fontSize: 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -151,6 +159,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextPrimary,
@@ -168,6 +177,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -185,6 +195,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark3,
@@ -202,6 +213,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 14,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark3,
@@ -219,6 +231,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 12,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle1,
@@ -237,6 +250,7 @@ class STextStyles {
           fontSize: 14,
           height: 14 / 14,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textFieldActiveSearchIconRight,
@@ -255,6 +269,7 @@ class STextStyles {
           fontWeight: FontWeight.w700,
           fontSize: 12,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle1,
@@ -272,6 +287,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 14,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).infoItemLabel,
@@ -289,6 +305,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 14,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -306,6 +323,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 14,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -324,6 +342,7 @@ class STextStyles {
           fontSize: 14,
           height: 1.5,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle2,
@@ -343,6 +362,7 @@ class STextStyles {
           fontSize: 14,
           height: 1.5,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -361,6 +381,7 @@ class STextStyles {
           fontWeight: FontWeight.w400,
           fontSize: 14,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -378,6 +399,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 14,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).accentColorRed,
@@ -395,6 +417,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 14,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).infoItemIcons,
@@ -412,6 +435,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 12,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).accentColorBlue,
@@ -429,6 +453,7 @@ class STextStyles {
           fontWeight: FontWeight.w600,
           fontSize: 12,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -446,6 +471,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 12,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -463,6 +489,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 12,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -480,6 +507,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 10,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textError,
@@ -497,6 +525,7 @@ class STextStyles {
           fontWeight: FontWeight.w500,
           fontSize: 10,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle1,
@@ -517,6 +546,7 @@ class STextStyles {
           fontSize: 40,
           height: 40 / 40,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -536,6 +566,7 @@ class STextStyles {
           fontSize: 32,
           height: 32 / 32,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -555,6 +586,7 @@ class STextStyles {
           fontSize: 24,
           height: 24 / 24,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -574,6 +606,7 @@ class STextStyles {
           fontSize: 20,
           height: 30 / 20,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -593,6 +626,7 @@ class STextStyles {
           fontSize: 20,
           height: 30 / 20,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -612,6 +646,7 @@ class STextStyles {
           fontSize: 20,
           height: 28 / 20,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -631,6 +666,7 @@ class STextStyles {
           fontSize: 24,
           height: 33 / 24,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -650,6 +686,7 @@ class STextStyles {
           fontSize: 20,
           height: 26 / 20,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextPrimary,
@@ -669,6 +706,7 @@ class STextStyles {
           fontSize: 20,
           height: 26 / 20,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextPrimaryDisabled,
@@ -688,6 +726,7 @@ class STextStyles {
           fontSize: 20,
           height: 26 / 20,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextSecondary,
@@ -707,6 +746,7 @@ class STextStyles {
           fontSize: 20,
           height: 26 / 20,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextSecondaryDisabled,
@@ -726,6 +766,7 @@ class STextStyles {
           fontSize: 18,
           height: 27 / 18,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextPrimaryDisabled,
@@ -745,6 +786,7 @@ class STextStyles {
           fontSize: 16,
           height: 24 / 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextPrimaryDisabled,
@@ -764,6 +806,7 @@ class STextStyles {
           fontSize: 14,
           height: 21 / 14,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle1,
@@ -783,6 +826,7 @@ class STextStyles {
           fontSize: 14,
           height: 21 / 14,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -802,6 +846,7 @@ class STextStyles {
           fontSize: 16,
           height: 24 / 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextSecondary,
@@ -821,6 +866,7 @@ class STextStyles {
           fontSize: 20,
           height: 30 / 20,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle2,
@@ -840,6 +886,7 @@ class STextStyles {
           fontSize: 16,
           height: 20.8 / 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark.withOpacity(0.8),
@@ -859,6 +906,7 @@ class STextStyles {
           fontSize: 16,
           height: 20.8 / 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -878,6 +926,7 @@ class STextStyles {
           fontSize: 16,
           height: 20.8 / 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark.withOpacity(0.5),
@@ -897,6 +946,7 @@ class STextStyles {
           fontSize: 16,
           height: 20.8 / 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -915,6 +965,7 @@ class STextStyles {
           fontWeight: FontWeight.w600,
           fontSize: 8,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.roboto(
           color: _theme(context).textDark,
@@ -932,6 +983,7 @@ class STextStyles {
           fontWeight: FontWeight.w400,
           fontSize: 26,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.roboto(
           color: _theme(context).numberTextDefault,
@@ -950,6 +1002,7 @@ class STextStyles {
           fontWeight: FontWeight.w400,
           fontSize: 12,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           letterSpacing: 0.5,
@@ -969,6 +1022,7 @@ class STextStyles {
           fontWeight: FontWeight.w600,
           fontSize: 16,
         );
+      case ThemeType.oceanBreeze:
       case ThemeType.dark:
         return GoogleFonts.inter(
           letterSpacing: 0.5,
diff --git a/lib/utilities/theme/color_theme.dart b/lib/utilities/theme/color_theme.dart
index 49fd41a6e..852e2f586 100644
--- a/lib/utilities/theme/color_theme.dart
+++ b/lib/utilities/theme/color_theme.dart
@@ -5,6 +5,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
 enum ThemeType {
   light,
   dark,
+  oceanBreeze,
 }
 
 abstract class StackColorTheme {

From 390c3f186ff8266479a38ce90684840b0f554042 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 18:49:56 -0600
Subject: [PATCH 028/100] temporarily disable in wallet exchange button

---
 .../wallet_view/desktop_wallet_view.dart      | 60 +++++++++----------
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
index a7de8fdf4..d08864eee 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
@@ -467,36 +467,36 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
                         );
                       },
                     ),
-                  if (coin == Coin.firo) const SizedBox(width: 16),
-                  SecondaryButton(
-                    width: 180,
-                    buttonHeight: ButtonHeight.l,
-                    onPressed: () {
-                      _onExchangePressed(context);
-                    },
-                    label: "Exchange",
-                    icon: Container(
-                      width: 24,
-                      height: 24,
-                      decoration: BoxDecoration(
-                        borderRadius: BorderRadius.circular(24),
-                        color: Theme.of(context)
-                            .extension<StackColors>()!
-                            .buttonBackPrimary
-                            .withOpacity(0.2),
-                      ),
-                      child: Center(
-                        child: SvgPicture.asset(
-                          Assets.svg.arrowRotate2,
-                          width: 14,
-                          height: 14,
-                          color: Theme.of(context)
-                              .extension<StackColors>()!
-                              .buttonTextSecondary,
-                        ),
-                      ),
-                    ),
-                  ),
+                  // if (coin == Coin.firo) const SizedBox(width: 16),
+                  // SecondaryButton(
+                  //   width: 180,
+                  //   buttonHeight: ButtonHeight.l,
+                  //   onPressed: () {
+                  //     _onExchangePressed(context);
+                  //   },
+                  //   label: "Exchange",
+                  //   icon: Container(
+                  //     width: 24,
+                  //     height: 24,
+                  //     decoration: BoxDecoration(
+                  //       borderRadius: BorderRadius.circular(24),
+                  //       color: Theme.of(context)
+                  //           .extension<StackColors>()!
+                  //           .buttonBackPrimary
+                  //           .withOpacity(0.2),
+                  //     ),
+                  //     child: Center(
+                  //       child: SvgPicture.asset(
+                  //         Assets.svg.arrowRotate2,
+                  //         width: 14,
+                  //         height: 14,
+                  //         color: Theme.of(context)
+                  //             .extension<StackColors>()!
+                  //             .buttonTextSecondary,
+                  //       ),
+                  //     ),
+                  //   ),
+                  // ),
                 ],
               ),
             ),

From 4eed147f10f978125f7ebaf1b57b7410732fe287 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Thu, 17 Nov 2022 19:23:15 -0600
Subject: [PATCH 029/100] update main to check for ocean breeze theme

---
 lib/main.dart | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/main.dart b/lib/main.dart
index b1f917f58..42b4ee718 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -301,6 +301,9 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
       case "dark":
         themeType = ThemeType.dark;
         break;
+      case "oceanBreeze":
+        themeType = ThemeType.oceanBreeze;
+        break;
       case "light":
       default:
         themeType = ThemeType.light;

From 2137cffd8459b750c9bd7b056eb46c93e0f60418 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Thu, 17 Nov 2022 20:04:02 -0700
Subject: [PATCH 030/100] ocean breeze theme colors added

---
 .../appearance_settings_view.dart             |   5 +-
 lib/utilities/text_styles.dart                | 296 +++++++++++++++++
 lib/utilities/theme/ocean_breeze_colors.dart  | 306 ++++++++++++++++++
 3 files changed, 606 insertions(+), 1 deletion(-)
 create mode 100644 lib/utilities/theme/ocean_breeze_colors.dart

diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart
index b0cf35a84..3a1b842f6 100644
--- a/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart
+++ b/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart
@@ -141,7 +141,10 @@ class AppearanceSettingsView extends ConsumerWidget {
                                             key: "colorScheme",
                                             value: (newValue
                                                     ? ThemeType.dark
-                                                    : ThemeType.light)
+                                                    : (newValue
+                                                        ? ThemeType.light
+                                                        : ThemeType
+                                                            .oceanBreeze))
                                                 .name,
                                           );
                                           ref
diff --git a/lib/utilities/text_styles.dart b/lib/utilities/text_styles.dart
index db4764459..c9dd15e1d 100644
--- a/lib/utilities/text_styles.dart
+++ b/lib/utilities/text_styles.dart
@@ -16,6 +16,11 @@ class STextStyles {
           fontSize: 20,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 20,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -34,6 +39,11 @@ class STextStyles {
           fontSize: 18,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 18,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -52,6 +62,11 @@ class STextStyles {
           fontSize: 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -70,6 +85,11 @@ class STextStyles {
           fontSize: 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -88,6 +108,11 @@ class STextStyles {
           fontSize: 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w400,
+          fontSize: 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -106,6 +131,11 @@ class STextStyles {
           fontSize: 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w400,
+          fontSize: 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -124,6 +154,11 @@ class STextStyles {
           fontSize: 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -142,6 +177,11 @@ class STextStyles {
           fontSize: 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -160,6 +200,11 @@ class STextStyles {
           fontSize: 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).buttonTextPrimary,
+          fontWeight: FontWeight.w500,
+          fontSize: 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextPrimary,
@@ -178,6 +223,11 @@ class STextStyles {
           fontSize: 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -196,6 +246,11 @@ class STextStyles {
           fontSize: 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark3,
+          fontWeight: FontWeight.w500,
+          fontSize: 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark3,
@@ -214,6 +269,11 @@ class STextStyles {
           fontSize: 14,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark3,
+          fontWeight: FontWeight.w500,
+          fontSize: 14,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark3,
@@ -232,6 +292,11 @@ class STextStyles {
           fontSize: 12,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textSubtitle1,
+          fontWeight: FontWeight.w500,
+          fontSize: 12,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle1,
@@ -251,6 +316,12 @@ class STextStyles {
           height: 14 / 14,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textFieldActiveSearchIconRight,
+          fontWeight: FontWeight.w500,
+          fontSize: 14,
+          height: 14 / 14,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textFieldActiveSearchIconRight,
@@ -270,6 +341,11 @@ class STextStyles {
           fontSize: 12,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textSubtitle1,
+          fontWeight: FontWeight.w700,
+          fontSize: 12,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle1,
@@ -288,6 +364,11 @@ class STextStyles {
           fontSize: 14,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).infoItemLabel,
+          fontWeight: FontWeight.w500,
+          fontSize: 14,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).infoItemLabel,
@@ -306,6 +387,11 @@ class STextStyles {
           fontSize: 14,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 14,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -324,6 +410,11 @@ class STextStyles {
           fontSize: 14,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 14,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -343,6 +434,12 @@ class STextStyles {
           height: 1.5,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textSubtitle2,
+          fontWeight: FontWeight.w500,
+          fontSize: 14,
+          height: 1.5,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle2,
@@ -363,6 +460,12 @@ class STextStyles {
           height: 1.5,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 14,
+          height: 1.5,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -382,6 +485,11 @@ class STextStyles {
           fontSize: 14,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w400,
+          fontSize: 14,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -400,6 +508,11 @@ class STextStyles {
           fontSize: 14,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).accentColorRed,
+          fontWeight: FontWeight.w500,
+          fontSize: 14,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).accentColorRed,
@@ -418,6 +531,11 @@ class STextStyles {
           fontSize: 14,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).infoItemIcons,
+          fontWeight: FontWeight.w500,
+          fontSize: 14,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).infoItemIcons,
@@ -436,6 +554,11 @@ class STextStyles {
           fontSize: 12,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).accentColorBlue,
+          fontWeight: FontWeight.w500,
+          fontSize: 12,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).accentColorBlue,
@@ -454,6 +577,11 @@ class STextStyles {
           fontSize: 12,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 12,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -472,6 +600,11 @@ class STextStyles {
           fontSize: 12,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 12,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -490,6 +623,11 @@ class STextStyles {
           fontSize: 12,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 12,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -508,6 +646,11 @@ class STextStyles {
           fontSize: 10,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textError,
+          fontWeight: FontWeight.w500,
+          fontSize: 10,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textError,
@@ -526,6 +669,11 @@ class STextStyles {
           fontSize: 10,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textSubtitle1,
+          fontWeight: FontWeight.w500,
+          fontSize: 10,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle1,
@@ -547,6 +695,12 @@ class STextStyles {
           height: 40 / 40,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 40,
+          height: 40 / 40,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -567,6 +721,12 @@ class STextStyles {
           height: 32 / 32,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 32,
+          height: 32 / 32,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -587,6 +747,12 @@ class STextStyles {
           height: 24 / 24,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 24,
+          height: 24 / 24,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -607,6 +773,12 @@ class STextStyles {
           height: 30 / 20,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 20,
+          height: 30 / 20,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -627,6 +799,12 @@ class STextStyles {
           height: 30 / 20,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w400,
+          fontSize: 20,
+          height: 30 / 20,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -647,6 +825,12 @@ class STextStyles {
           height: 28 / 20,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w400,
+          fontSize: 20,
+          height: 28 / 20,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -667,6 +851,12 @@ class STextStyles {
           height: 33 / 24,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w400,
+          fontSize: 24,
+          height: 33 / 24,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -687,6 +877,12 @@ class STextStyles {
           height: 26 / 20,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).buttonTextPrimary,
+          fontWeight: FontWeight.w500,
+          fontSize: 20,
+          height: 26 / 20,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextPrimary,
@@ -707,6 +903,12 @@ class STextStyles {
           height: 26 / 20,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).buttonTextPrimaryDisabled,
+          fontWeight: FontWeight.w500,
+          fontSize: 20,
+          height: 26 / 20,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextPrimaryDisabled,
@@ -727,6 +929,12 @@ class STextStyles {
           height: 26 / 20,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).buttonTextSecondary,
+          fontWeight: FontWeight.w500,
+          fontSize: 20,
+          height: 26 / 20,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextSecondary,
@@ -747,6 +955,12 @@ class STextStyles {
           height: 26 / 20,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).buttonTextSecondaryDisabled,
+          fontWeight: FontWeight.w500,
+          fontSize: 20,
+          height: 26 / 20,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextSecondaryDisabled,
@@ -767,6 +981,12 @@ class STextStyles {
           height: 27 / 18,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 18,
+          height: 27 / 18,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextPrimaryDisabled,
@@ -787,6 +1007,12 @@ class STextStyles {
           height: 24 / 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).buttonTextPrimaryDisabled,
+          fontWeight: FontWeight.w500,
+          fontSize: 16,
+          height: 24 / 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextPrimaryDisabled,
@@ -807,6 +1033,12 @@ class STextStyles {
           height: 21 / 14,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textSubtitle1,
+          fontWeight: FontWeight.w500,
+          fontSize: 14,
+          height: 21 / 14,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle1,
@@ -827,6 +1059,12 @@ class STextStyles {
           height: 21 / 14,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 14,
+          height: 21 / 14,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -847,6 +1085,12 @@ class STextStyles {
           height: 24 / 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).buttonTextSecondary,
+          fontWeight: FontWeight.w500,
+          fontSize: 16,
+          height: 24 / 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).buttonTextSecondary,
@@ -867,6 +1111,12 @@ class STextStyles {
           height: 30 / 20,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textSubtitle2,
+          fontWeight: FontWeight.w500,
+          fontSize: 20,
+          height: 30 / 20,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textSubtitle2,
@@ -887,6 +1137,12 @@ class STextStyles {
           height: 20.8 / 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark.withOpacity(0.8),
+          fontWeight: FontWeight.w500,
+          fontSize: 16,
+          height: 20.8 / 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark.withOpacity(0.8),
@@ -907,6 +1163,12 @@ class STextStyles {
           height: 20.8 / 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 16,
+          height: 20.8 / 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -927,6 +1189,12 @@ class STextStyles {
           height: 20.8 / 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark.withOpacity(0.5),
+          fontWeight: FontWeight.w500,
+          fontSize: 16,
+          height: 20.8 / 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark.withOpacity(0.5),
@@ -947,6 +1215,12 @@ class STextStyles {
           height: 20.8 / 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w500,
+          fontSize: 16,
+          height: 20.8 / 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           color: _theme(context).textDark,
@@ -966,6 +1240,11 @@ class STextStyles {
           fontSize: 8,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.roboto(
+          color: _theme(context).textDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 8,
+        );
       case ThemeType.dark:
         return GoogleFonts.roboto(
           color: _theme(context).textDark,
@@ -984,6 +1263,11 @@ class STextStyles {
           fontSize: 26,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.roboto(
+          color: _theme(context).numberTextDefault,
+          fontWeight: FontWeight.w400,
+          fontSize: 26,
+        );
       case ThemeType.dark:
         return GoogleFonts.roboto(
           color: _theme(context).numberTextDefault,
@@ -1003,6 +1287,12 @@ class STextStyles {
           fontSize: 12,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          letterSpacing: 0.5,
+          color: _theme(context).accentColorDark,
+          fontWeight: FontWeight.w400,
+          fontSize: 12,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           letterSpacing: 0.5,
@@ -1023,6 +1313,12 @@ class STextStyles {
           fontSize: 16,
         );
       case ThemeType.oceanBreeze:
+        return GoogleFonts.inter(
+          letterSpacing: 0.5,
+          color: _theme(context).accentColorDark,
+          fontWeight: FontWeight.w600,
+          fontSize: 16,
+        );
       case ThemeType.dark:
         return GoogleFonts.inter(
           letterSpacing: 0.5,
diff --git a/lib/utilities/theme/ocean_breeze_colors.dart b/lib/utilities/theme/ocean_breeze_colors.dart
new file mode 100644
index 000000000..ff2f4e85e
--- /dev/null
+++ b/lib/utilities/theme/ocean_breeze_colors.dart
@@ -0,0 +1,306 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/utilities/theme/color_theme.dart';
+
+class OceanBreezeColors extends StackColorTheme {
+  @override
+  ThemeType get themeType => ThemeType.oceanBreeze;
+
+  @override
+  Color get background => const Color(0xFFF3F7FA);
+  @override
+  Color get overlay => const Color(0xFF111215);
+
+  @override
+  Color get accentColorBlue => const Color(0xFF077CBE);
+  @override
+  Color get accentColorGreen => const Color(0xFF00A591);
+  @override
+  Color get accentColorYellow => const Color(0xFFF4C517);
+  @override
+  Color get accentColorRed => const Color(0xFFD1382D);
+  @override
+  Color get accentColorOrange => const Color(0xFFFF985F);
+  @override
+  Color get accentColorDark => const Color(0xFF232323);
+
+  @override
+  Color get shadow => const Color(0xFF388192);
+
+  @override
+  Color get textDark => const Color(0xFF232323);
+  @override
+  Color get textDark2 => const Color(0xFF333333);
+  @override
+  Color get textDark3 => const Color(0xFF696B6C);
+  @override
+  Color get textSubtitle1 => const Color(0xFF7E8284);
+  @override
+  Color get textSubtitle2 => const Color(0xFF919393);
+  @override
+  Color get textSubtitle3 => const Color(0xFFB0B2B2);
+  @override
+  Color get textSubtitle4 => const Color(0xFFD1D3D3);
+  @override
+  Color get textSubtitle5 => const Color(0xFFDEDFE1);
+  @override
+  Color get textSubtitle6 => const Color(0xFFF1F1F1);
+  @override
+  Color get textWhite => const Color(0xFFFFFFFF);
+  @override
+  Color get textFavoriteCard => const Color(0xFF232323);
+  @override
+  Color get textError => const Color(0xFF8D0006);
+
+  // button background
+  @override
+  Color get buttonBackPrimary => const Color(0xFF227386);
+  @override
+  Color get buttonBackSecondary => const Color(0xFFC2DAE2);
+  @override
+  Color get buttonBackPrimaryDisabled => const Color(0xFFBDD5DB);
+  @override
+  Color get buttonBackSecondaryDisabled => const Color(0xFFBDBDBD);
+  @override
+  Color get buttonBackBorder => const Color(0xFF227386);
+  @override
+  Color get buttonBackBorderDisabled => const Color(0xFFBDD5DB);
+
+  @override
+  Color get numberBackDefault => const Color(0xFFFFFFFF);
+  @override
+  Color get numpadBackDefault => const Color(0xFF227386);
+  @override
+  Color get bottomNavBack => const Color(0xFFFFFFFF);
+
+  // button text/element
+  @override
+  Color get buttonTextPrimary => const Color(0xFFFFFFFF);
+  @override
+  Color get buttonTextSecondary => const Color(0xFF232323);
+  @override
+  Color get buttonTextPrimaryDisabled => const Color(0xFFFFFFFF);
+  @override
+  Color get buttonTextSecondaryDisabled => const Color(0xFFBDD5DB);
+  @override
+  Color get buttonTextBorder => const Color(0xFF227386);
+  @override
+  Color get buttonTextDisabled => const Color(0xFFFFFFFF);
+  @override
+  Color get buttonTextBorderless => const Color(0xFF056EC6);
+  @override
+  Color get buttonTextBorderlessDisabled => const Color(0xFFB6B6B6);
+  @override
+  Color get numberTextDefault => const Color(0xFF232323);
+  @override
+  Color get numpadTextDefault => const Color(0xFFFFFFFF);
+  @override
+  Color get bottomNavText => const Color(0xFF232323);
+
+  // switch
+  @override
+  Color get switchBGOn => const Color(0xFF056EC6);
+  @override
+  Color get switchBGOff => const Color(0xFFCCDBF9);
+  @override
+  Color get switchBGDisabled => const Color(0xFFC5C6C9);
+  @override
+  Color get switchCircleOn => const Color(0xFFDAE2FF);
+  @override
+  Color get switchCircleOff => const Color(0xFFFBFCFF);
+  @override
+  Color get switchCircleDisabled => const Color(0xFFFBFCFF);
+
+  // step indicator background
+  @override
+  Color get stepIndicatorBGCheck => const Color(0xFFCDD9FF);
+  @override
+  Color get stepIndicatorBGNumber => const Color(0xFFCDD9FF);
+  @override
+  Color get stepIndicatorBGInactive => const Color(0xFFA6C7D1);
+  @override
+  Color get stepIndicatorBGLines => const Color(0xFF90B8DC);
+  @override
+  Color get stepIndicatorBGLinesInactive => const Color(0xFFBCD4EA);
+  @override
+  Color get stepIndicatorIconText => const Color(0xFF005BAF);
+  @override
+  Color get stepIndicatorIconNumber => const Color(0xFF005BAF);
+  @override
+  Color get stepIndicatorIconInactive => const Color(0xFFD4DFFF);
+
+  // checkbox
+  @override
+  Color get checkboxBGChecked => const Color(0xFF056EC6);
+  @override
+  Color get checkboxBorderEmpty => const Color(0xFF8C8F90);
+  @override
+  Color get checkboxBGDisabled => const Color(0xFFB0C9ED);
+  @override
+  Color get checkboxIconChecked => const Color(0xFFFFFFFF);
+  @override
+  Color get checkboxIconDisabled => const Color(0xFFFFFFFF);
+  @override
+  Color get checkboxTextLabel => const Color(0xFF232323);
+
+  // snack bar
+  @override
+  Color get snackBarBackSuccess => const Color(0xFFADD6D2);
+  @override
+  Color get snackBarBackError => const Color(0xFFF6C7C3);
+  @override
+  Color get snackBarBackInfo => const Color(0xFFCCD7FF);
+  @override
+  Color get snackBarTextSuccess => const Color(0xFF075547);
+  @override
+  Color get snackBarTextError => const Color(0xFF8D0006);
+  @override
+  Color get snackBarTextInfo => const Color(0xFF002569);
+
+  // icons
+  @override
+  Color get bottomNavIconBack => const Color(0xFFA7C7CF);
+  @override
+  Color get bottomNavIconIcon => const Color(0xFF227386);
+
+  @override
+  Color get topNavIconPrimary => const Color(0xFF227386);
+  @override
+  Color get topNavIconGreen => const Color(0xFF00A591);
+  @override
+  Color get topNavIconYellow => const Color(0xFFFDD33A);
+  @override
+  Color get topNavIconRed => const Color(0xFFEA4649);
+
+  @override
+  Color get settingsIconBack => const Color(0xFFE0E3E3);
+  @override
+  Color get settingsIconIcon => const Color(0xFF232323);
+  @override
+  Color get settingsIconBack2 => const Color(0xFF80D2C8);
+  @override
+  Color get settingsIconElement => const Color(0xFF00A591);
+
+  // text field
+  @override
+  Color get textFieldActiveBG => const Color(0xFFD3E3E7);
+  @override
+  Color get textFieldDefaultBG => const Color(0xFFD8E7EB);
+  @override
+  Color get textFieldErrorBG => const Color(0xFFF6C7C3);
+  @override
+  Color get textFieldSuccessBG => const Color(0xFFADD6D2);
+
+  @override
+  Color get textFieldActiveSearchIconLeft => const Color(0xFF86898C);
+  @override
+  Color get textFieldDefaultSearchIconLeft => const Color(0xFF86898C);
+  @override
+  Color get textFieldErrorSearchIconLeft => const Color(0xFF8D0006);
+  @override
+  Color get textFieldSuccessSearchIconLeft => const Color(0xFF006C4D);
+
+  @override
+  Color get textFieldActiveText => const Color(0xFF232323);
+  @override
+  Color get textFieldDefaultText => const Color(0xFF86898C);
+  @override
+  Color get textFieldErrorText => const Color(0xFF000000);
+  @override
+  Color get textFieldSuccessText => const Color(0xFF000000);
+
+  @override
+  Color get textFieldActiveLabel => const Color(0xFF86898C);
+  @override
+  Color get textFieldErrorLabel => const Color(0xFF8D0006);
+  @override
+  Color get textFieldSuccessLabel => const Color(0xFF077C6E);
+
+  @override
+  Color get textFieldActiveSearchIconRight => const Color(0xFF388192);
+  @override
+  Color get textFieldDefaultSearchIconRight => const Color(0xFF388192);
+  @override
+  Color get textFieldErrorSearchIconRight => const Color(0xFF8D0006);
+  @override
+  Color get textFieldSuccessSearchIconRight => const Color(0xFF077C6E);
+
+  // settings item level2
+  @override
+  Color get settingsItem2ActiveBG => const Color(0xFFFFFFFF);
+  @override
+  Color get settingsItem2ActiveText => const Color(0xFF232323);
+  @override
+  Color get settingsItem2ActiveSub => const Color(0xFF8C8F90);
+
+  // radio buttons
+  @override
+  Color get radioButtonIconBorder => const Color(0xFF056EC6);
+  @override
+  Color get radioButtonIconBorderDisabled => const Color(0xFF8C8D97);
+  @override
+  Color get radioButtonBorderEnabled => const Color(0xFF056EC6);
+  @override
+  Color get radioButtonBorderDisabled => const Color(0xFF8C8D97);
+  @override
+  Color get radioButtonIconCircle => const Color(0xFF056EC6);
+  @override
+  Color get radioButtonIconEnabled => const Color(0xFF056EC6);
+  @override
+  Color get radioButtonTextEnabled => const Color(0xFF42444B);
+  @override
+  Color get radioButtonTextDisabled => const Color(0xFF42444B);
+  @override
+  Color get radioButtonLabelEnabled => const Color(0xFF8C8F90);
+  @override
+  Color get radioButtonLabelDisabled => const Color(0xFF8C8F90);
+
+  // info text
+  @override
+  Color get infoItemBG => const Color(0xFFFFFFFF);
+  @override
+  Color get infoItemLabel => const Color(0xFF838788);
+  @override
+  Color get infoItemText => const Color(0xFF232323);
+  @override
+  Color get infoItemIcons => const Color(0xFF056EC6);
+
+  // popup
+  @override
+  Color get popupBG => const Color(0xFFFFFFFF);
+
+  // currency list
+  @override
+  Color get currencyListItemBG => const Color(0xFFF0F5F7);
+
+  // bottom nav
+  @override
+  Color get stackWalletBG => const Color(0xFFFFFFFF);
+  @override
+  Color get stackWalletMid => const Color(0xFFFFFFFF);
+  @override
+  Color get stackWalletBottom => const Color(0xFF232323);
+  @override
+  Color get bottomNavShadow => const Color(0xFF388192);
+
+  @override
+  Color get favoriteStarActive => const Color(0xFFF4C517);
+  @override
+  Color get favoriteStarInactive => const Color(0xFFB0B2B2);
+
+  @override
+  Color get splash => const Color(0xFF8E9192);
+  @override
+  Color get highlight => const Color(0xFFA9ACAC);
+  @override
+  Color get warningForeground => const Color(0xFF232323);
+  @override
+  Color get warningBackground => const Color(0xFFF6C7C3);
+  @override
+  Color get loadingOverlayTextColor => const Color(0xFFF7F7F7);
+  @override
+  Color get myStackContactIconBG => const Color(0xFFD8E7EB);
+  @override
+  Color get textConfirmTotalAmount => const Color(0xFF232323);
+  @override
+  Color get textSelectedWordTableItem => const Color(0xFF232323);
+}

From 02dadd432ca70d30197ca510474b8ee4bb29ba1b Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Thu, 17 Nov 2022 20:05:29 -0700
Subject: [PATCH 031/100] ocean breeze added

---
 lib/main.dart | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/lib/main.dart b/lib/main.dart
index 42b4ee718..2d1bab160 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -57,6 +57,7 @@ import 'package:stackwallet/utilities/stack_file_system.dart';
 import 'package:stackwallet/utilities/theme/color_theme.dart';
 import 'package:stackwallet/utilities/theme/dark_colors.dart';
 import 'package:stackwallet/utilities/theme/light_colors.dart';
+import 'package:stackwallet/utilities/theme/ocean_breeze_colors.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/utilities/util.dart';
 import 'package:window_size/window_size.dart';
@@ -317,8 +318,11 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
 
     WidgetsBinding.instance.addPostFrameCallback((_) async {
       ref.read(colorThemeProvider.state).state =
-          StackColors.fromStackColorTheme(
-              themeType == ThemeType.dark ? DarkColors() : LightColors());
+          StackColors.fromStackColorTheme(themeType == ThemeType.dark
+              ? DarkColors()
+              : (themeType == ThemeType.light
+                  ? LightColors()
+                  : OceanBreezeColors()));
 
       if (Platform.isAndroid) {
         // fetch open file if it exists

From 17e4976a899b3a0f5ceecd20edf10d1495a0568c Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 09:07:11 -0600
Subject: [PATCH 032/100] include flushbartype in flushbar import

---
 lib/notifications/show_flush_bar.dart | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/notifications/show_flush_bar.dart b/lib/notifications/show_flush_bar.dart
index 5320c8a9d..47cea682a 100644
--- a/lib/notifications/show_flush_bar.dart
+++ b/lib/notifications/show_flush_bar.dart
@@ -6,6 +6,8 @@ import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 
+export 'package:stackwallet/utilities/enums/flush_bar_type.dart';
+
 Future<dynamic> showFloatingFlushBar({
   required FlushBarType type,
   required String message,

From aa966a106dd3c603da01bf3d24b3f6358441399c Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 09:07:31 -0600
Subject: [PATCH 033/100] add delete contact functionality for desktop

---
 .../subwidgets/desktop_contact_details.dart   | 382 ++++++++++++------
 lib/widgets/address_book_card.dart            |  13 +-
 2 files changed, 260 insertions(+), 135 deletions(-)

diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
index 2cd20a839..96eed4835 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
@@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 import 'package:stackwallet/models/contact.dart';
 import 'package:stackwallet/models/paymint/transactions_model.dart';
+import 'package:stackwallet/notifications/show_flush_bar.dart';
 import 'package:stackwallet/pages/address_book_views/subviews/add_new_contact_address_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart';
 import 'package:stackwallet/providers/global/address_book_service_provider.dart';
@@ -15,6 +16,8 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
@@ -74,8 +77,16 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
 
   @override
   Widget build(BuildContext context) {
-    final contact = ref.watch(addressBookServiceProvider
-        .select((value) => value.getContactById(widget.contactId)));
+    // provider hack to prevent trying to update widget with deleted contact
+    Contact? _contact;
+    try {
+      _contact = ref.watch(addressBookServiceProvider
+          .select((value) => value.getContactById(widget.contactId)));
+    } catch (_) {
+      return Container();
+    }
+
+    final contact = _contact!;
 
     return Row(
       crossAxisAlignment: CrossAxisAlignment.start,
@@ -129,22 +140,23 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
                         ),
                       ],
                     ),
-                    SecondaryButton(
-                      label: "Options",
-                      width: 96,
-                      buttonHeight: ButtonHeight.xxs,
-                      onPressed: () async {
-                        await showDialog<void>(
-                          context: context,
-                          barrierColor: Colors.transparent,
-                          builder: (context) {
-                            return DesktopContactOptionsMenuPopup(
-                              contactId: contact.id,
-                            );
-                          },
-                        );
-                      },
-                    ),
+                    if (widget.contactId != "default")
+                      SecondaryButton(
+                        label: "Options",
+                        width: 96,
+                        buttonHeight: ButtonHeight.xxs,
+                        onPressed: () async {
+                          await showDialog<void>(
+                            context: context,
+                            barrierColor: Colors.transparent,
+                            builder: (context) {
+                              return DesktopContactOptionsMenuPopup(
+                                contactId: contact.id,
+                              );
+                            },
+                          );
+                        },
+                      ),
                   ],
                 ),
                 const SizedBox(
@@ -453,132 +465,238 @@ class _DesktopContactOptionsMenuPopupState
                       ),
                     ),
                   ),
-                  const SizedBox(
-                    height: 2,
-                  ),
-                  MouseRegion(
-                    onEnter: (_) {
-                      setState(() {
-                        hoveredOnPencil = true;
-                      });
-                    },
-                    onExit: (_) {
-                      setState(() {
-                        hoveredOnPencil = false;
-                      });
-                    },
-                    child: RawMaterialButton(
-                      hoverColor: Theme.of(context)
-                          .extension<StackColors>()!
-                          .textFieldDefaultBG,
-                      shape: RoundedRectangleBorder(
-                        borderRadius: BorderRadius.circular(
-                          1000,
-                        ),
-                      ),
-                      onPressed: () {
-                        print("should go to edit");
+                  if (widget.contactId != "default")
+                    const SizedBox(
+                      height: 2,
+                    ),
+                  if (widget.contactId != "default")
+                    MouseRegion(
+                      onEnter: (_) {
+                        setState(() {
+                          hoveredOnPencil = true;
+                        });
                       },
-                      child: Padding(
-                        padding: const EdgeInsets.symmetric(
-                          horizontal: 25,
-                          vertical: 16,
+                      onExit: (_) {
+                        setState(() {
+                          hoveredOnPencil = false;
+                        });
+                      },
+                      child: RawMaterialButton(
+                        hoverColor: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textFieldDefaultBG,
+                        shape: RoundedRectangleBorder(
+                          borderRadius: BorderRadius.circular(
+                            1000,
+                          ),
                         ),
-                        child: Row(
-                          children: [
-                            SvgPicture.asset(
-                              Assets.svg.pencil,
-                              width: 24,
-                              height: 22,
-                              color: hoveredOnPencil
-                                  ? Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textDark
-                                  : Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textFieldDefaultSearchIconLeft,
-                            ),
-                            const SizedBox(
-                              width: 12,
-                            ),
-                            Text(
-                              "Edit contact",
-                              style: STextStyles.desktopTextExtraExtraSmall(
-                                      context)
-                                  .copyWith(
-                                color: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .textDark,
+                        onPressed: () {
+                          print("should go to edit");
+                        },
+                        child: Padding(
+                          padding: const EdgeInsets.symmetric(
+                            horizontal: 25,
+                            vertical: 16,
+                          ),
+                          child: Row(
+                            children: [
+                              SvgPicture.asset(
+                                Assets.svg.pencil,
+                                width: 24,
+                                height: 22,
+                                color: hoveredOnPencil
+                                    ? Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textDark
+                                    : Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textFieldDefaultSearchIconLeft,
                               ),
-                            )
-                          ],
+                              const SizedBox(
+                                width: 12,
+                              ),
+                              Text(
+                                "Edit contact",
+                                style: STextStyles.desktopTextExtraExtraSmall(
+                                        context)
+                                    .copyWith(
+                                  color: Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark,
+                                ),
+                              )
+                            ],
+                          ),
                         ),
                       ),
                     ),
-                  ),
-                  const SizedBox(
-                    height: 2,
-                  ),
-                  MouseRegion(
-                    onEnter: (_) {
-                      setState(() {
-                        hoveredOnTrash = true;
-                      });
-                    },
-                    onExit: (_) {
-                      setState(() {
-                        hoveredOnTrash = false;
-                      });
-                    },
-                    child: RawMaterialButton(
-                      hoverColor: Theme.of(context)
-                          .extension<StackColors>()!
-                          .textFieldDefaultBG,
-                      shape: RoundedRectangleBorder(
-                        borderRadius: BorderRadius.circular(
-                          1000,
-                        ),
-                      ),
-                      onPressed: () {
-                        print("should delete contact");
+                  if (widget.contactId != "default")
+                    const SizedBox(
+                      height: 2,
+                    ),
+                  if (widget.contactId != "default")
+                    MouseRegion(
+                      onEnter: (_) {
+                        setState(() {
+                          hoveredOnTrash = true;
+                        });
                       },
-                      child: Padding(
-                        padding: const EdgeInsets.symmetric(
-                          horizontal: 25,
-                          vertical: 16,
+                      onExit: (_) {
+                        setState(() {
+                          hoveredOnTrash = false;
+                        });
+                      },
+                      child: RawMaterialButton(
+                        hoverColor: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textFieldDefaultBG,
+                        shape: RoundedRectangleBorder(
+                          borderRadius: BorderRadius.circular(
+                            1000,
+                          ),
                         ),
-                        child: Row(
-                          children: [
-                            SvgPicture.asset(
-                              Assets.svg.trash,
-                              width: 24,
-                              height: 22,
-                              color: hoveredOnTrash
-                                  ? Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textDark
-                                  : Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textFieldDefaultSearchIconLeft,
-                            ),
-                            const SizedBox(
-                              width: 12,
-                            ),
-                            Text(
-                              "Delete contact",
-                              style: STextStyles.desktopTextExtraExtraSmall(
-                                      context)
-                                  .copyWith(
-                                color: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .textDark,
+                        onPressed: () {
+                          final contact = ref
+                              .read(addressBookServiceProvider)
+                              .getContactById(widget.contactId);
+
+                          // pop context menu
+                          Navigator.of(context).pop();
+
+                          showDialog<dynamic>(
+                            context: context,
+                            useSafeArea: true,
+                            barrierDismissible: true,
+                            builder: (_) => DesktopDialog(
+                              maxWidth: 500,
+                              maxHeight: 300,
+                              child: Column(
+                                children: [
+                                  Row(
+                                    mainAxisAlignment:
+                                        MainAxisAlignment.spaceBetween,
+                                    children: [
+                                      Padding(
+                                        padding: const EdgeInsets.only(
+                                          left: 32,
+                                        ),
+                                        child: Text(
+                                          "Delete ${contact.name}?",
+                                          style: STextStyles.desktopH3(context),
+                                        ),
+                                      ),
+                                      const DesktopDialogCloseButton(),
+                                    ],
+                                  ),
+                                  Expanded(
+                                    child: Padding(
+                                      padding: const EdgeInsets.only(
+                                        left: 32,
+                                        right: 32,
+                                        bottom: 32,
+                                      ),
+                                      child: Column(
+                                        crossAxisAlignment:
+                                            CrossAxisAlignment.start,
+                                        children: [
+                                          const Spacer(
+                                            flex: 1,
+                                          ),
+                                          Text(
+                                            "Contact will be deleted permanently!",
+                                            style: STextStyles.desktopTextSmall(
+                                                context),
+                                          ),
+                                          const Spacer(
+                                            flex: 2,
+                                          ),
+                                          Row(
+                                            children: [
+                                              Expanded(
+                                                child: SecondaryButton(
+                                                  label: "Cancel",
+                                                  onPressed:
+                                                      Navigator.of(context).pop,
+                                                  buttonHeight: ButtonHeight.l,
+                                                ),
+                                              ),
+                                              const SizedBox(
+                                                width: 16,
+                                              ),
+                                              Expanded(
+                                                child: Consumer(
+                                                  builder: (context, ref, __) =>
+                                                      PrimaryButton(
+                                                    label: "Delete",
+                                                    buttonHeight:
+                                                        ButtonHeight.l,
+                                                    onPressed: () {
+                                                      ref
+                                                          .read(
+                                                              addressBookServiceProvider)
+                                                          .removeContact(
+                                                              contact.id);
+                                                      Navigator.of(context)
+                                                          .pop();
+                                                      showFloatingFlushBar(
+                                                        type: FlushBarType
+                                                            .success,
+                                                        message:
+                                                            "${contact.name} deleted",
+                                                        context: context,
+                                                      );
+                                                    },
+                                                  ),
+                                                ),
+                                              ),
+                                            ],
+                                          )
+                                        ],
+                                      ),
+                                    ),
+                                  ),
+                                ],
                               ),
-                            )
-                          ],
+                            ),
+                          );
+                        },
+                        child: Padding(
+                          padding: const EdgeInsets.symmetric(
+                            horizontal: 25,
+                            vertical: 16,
+                          ),
+                          child: Row(
+                            children: [
+                              SvgPicture.asset(
+                                Assets.svg.trash,
+                                width: 24,
+                                height: 22,
+                                color: hoveredOnTrash
+                                    ? Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textDark
+                                    : Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textFieldDefaultSearchIconLeft,
+                              ),
+                              const SizedBox(
+                                width: 12,
+                              ),
+                              Text(
+                                "Delete contact",
+                                style: STextStyles.desktopTextExtraExtraSmall(
+                                        context)
+                                    .copyWith(
+                                  color: Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark,
+                                ),
+                              )
+                            ],
+                          ),
                         ),
                       ),
                     ),
-                  ),
                 ],
               ),
             ),
diff --git a/lib/widgets/address_book_card.dart b/lib/widgets/address_book_card.dart
index b79f89662..dfa655f86 100644
--- a/lib/widgets/address_book_card.dart
+++ b/lib/widgets/address_book_card.dart
@@ -1,6 +1,7 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/svg.dart';
+import 'package:stackwallet/models/contact.dart';
 import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart';
 import 'package:stackwallet/providers/global/address_book_service_provider.dart';
 import 'package:stackwallet/utilities/assets.dart';
@@ -44,10 +45,16 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
 
   @override
   Widget build(BuildContext context) {
-    // final isTiny = SizingUtilities.isTinyWidth(context);
+    // provider hack to prevent trying to update widget with deleted contact
+    Contact? _contact;
+    try {
+      _contact = ref.watch(addressBookServiceProvider
+          .select((value) => value.getContactById(contactId)));
+    } catch (_) {
+      return Container();
+    }
 
-    final contact = ref.watch(addressBookServiceProvider
-        .select((value) => value.getContactById(contactId)));
+    final contact = _contact!;
 
     final List<Coin> coins = [];
     for (var element in contact.addresses) {

From 07f229f2a0089a8a566ea846fa1e1d00b0fcc181 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 09:19:48 -0600
Subject: [PATCH 034/100] refactor popup

---
 .../subwidgets/desktop_contact_details.dart   | 358 +----------------
 .../desktop_contact_options_menu_popup.dart   | 366 ++++++++++++++++++
 2 files changed, 367 insertions(+), 357 deletions(-)
 create mode 100644 lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_options_menu_popup.dart

diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
index 96eed4835..62cd993af 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_details.dart
@@ -3,9 +3,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 import 'package:stackwallet/models/contact.dart';
 import 'package:stackwallet/models/paymint/transactions_model.dart';
-import 'package:stackwallet/notifications/show_flush_bar.dart';
 import 'package:stackwallet/pages/address_book_views/subviews/add_new_contact_address_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/address_book_view/subwidgets/desktop_address_card.dart';
+import 'package:stackwallet/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_options_menu_popup.dart';
 import 'package:stackwallet/providers/global/address_book_service_provider.dart';
 import 'package:stackwallet/providers/global/wallets_provider.dart';
 import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
@@ -16,8 +16,6 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
-import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
-import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
@@ -352,357 +350,3 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
     );
   }
 }
-
-class DesktopContactOptionsMenuPopup extends ConsumerStatefulWidget {
-  const DesktopContactOptionsMenuPopup({Key? key, required this.contactId})
-      : super(key: key);
-
-  final String contactId;
-
-  @override
-  ConsumerState<DesktopContactOptionsMenuPopup> createState() =>
-      _DesktopContactOptionsMenuPopupState();
-}
-
-class _DesktopContactOptionsMenuPopupState
-    extends ConsumerState<DesktopContactOptionsMenuPopup> {
-  bool hoveredOnStar = false;
-  bool hoveredOnPencil = false;
-  bool hoveredOnTrash = false;
-
-  @override
-  Widget build(BuildContext context) {
-    return Stack(
-      children: [
-        Positioned(
-          top: 210,
-          left: MediaQuery.of(context).size.width - 280,
-          child: Container(
-            width: 270,
-            decoration: BoxDecoration(
-              color: Theme.of(context).extension<StackColors>()!.popupBG,
-              borderRadius: BorderRadius.circular(
-                20,
-              ),
-              boxShadow: [
-                Theme.of(context).extension<StackColors>()!.standardBoxShadow,
-              ],
-            ),
-            child: Padding(
-              padding: const EdgeInsets.all(16),
-              child: Column(
-                children: [
-                  MouseRegion(
-                    onEnter: (_) {
-                      setState(() {
-                        hoveredOnStar = true;
-                      });
-                    },
-                    onExit: (_) {
-                      setState(() {
-                        hoveredOnStar = false;
-                      });
-                    },
-                    child: RawMaterialButton(
-                      hoverColor: Theme.of(context)
-                          .extension<StackColors>()!
-                          .textFieldDefaultBG,
-                      shape: RoundedRectangleBorder(
-                        borderRadius: BorderRadius.circular(
-                          1000,
-                        ),
-                      ),
-                      onPressed: () {
-                        final contact =
-                            ref.read(addressBookServiceProvider).getContactById(
-                                  widget.contactId,
-                                );
-                        ref.read(addressBookServiceProvider).editContact(
-                              contact.copyWith(
-                                isFavorite: !contact.isFavorite,
-                              ),
-                            );
-                      },
-                      child: Padding(
-                        padding: const EdgeInsets.symmetric(
-                          horizontal: 25,
-                          vertical: 16,
-                        ),
-                        child: Row(
-                          children: [
-                            SvgPicture.asset(
-                              Assets.svg.star,
-                              width: 24,
-                              height: 22,
-                              color: hoveredOnStar
-                                  ? Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textDark
-                                  : Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textFieldDefaultSearchIconLeft,
-                            ),
-                            const SizedBox(
-                              width: 12,
-                            ),
-                            Text(
-                              ref.watch(addressBookServiceProvider.select(
-                                      (value) => value
-                                          .getContactById(widget.contactId)
-                                          .isFavorite))
-                                  ? "Remove from favorites"
-                                  : "Add to favorites",
-                              style: STextStyles.desktopTextExtraExtraSmall(
-                                      context)
-                                  .copyWith(
-                                color: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .textDark,
-                              ),
-                            )
-                          ],
-                        ),
-                      ),
-                    ),
-                  ),
-                  if (widget.contactId != "default")
-                    const SizedBox(
-                      height: 2,
-                    ),
-                  if (widget.contactId != "default")
-                    MouseRegion(
-                      onEnter: (_) {
-                        setState(() {
-                          hoveredOnPencil = true;
-                        });
-                      },
-                      onExit: (_) {
-                        setState(() {
-                          hoveredOnPencil = false;
-                        });
-                      },
-                      child: RawMaterialButton(
-                        hoverColor: Theme.of(context)
-                            .extension<StackColors>()!
-                            .textFieldDefaultBG,
-                        shape: RoundedRectangleBorder(
-                          borderRadius: BorderRadius.circular(
-                            1000,
-                          ),
-                        ),
-                        onPressed: () {
-                          print("should go to edit");
-                        },
-                        child: Padding(
-                          padding: const EdgeInsets.symmetric(
-                            horizontal: 25,
-                            vertical: 16,
-                          ),
-                          child: Row(
-                            children: [
-                              SvgPicture.asset(
-                                Assets.svg.pencil,
-                                width: 24,
-                                height: 22,
-                                color: hoveredOnPencil
-                                    ? Theme.of(context)
-                                        .extension<StackColors>()!
-                                        .textDark
-                                    : Theme.of(context)
-                                        .extension<StackColors>()!
-                                        .textFieldDefaultSearchIconLeft,
-                              ),
-                              const SizedBox(
-                                width: 12,
-                              ),
-                              Text(
-                                "Edit contact",
-                                style: STextStyles.desktopTextExtraExtraSmall(
-                                        context)
-                                    .copyWith(
-                                  color: Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textDark,
-                                ),
-                              )
-                            ],
-                          ),
-                        ),
-                      ),
-                    ),
-                  if (widget.contactId != "default")
-                    const SizedBox(
-                      height: 2,
-                    ),
-                  if (widget.contactId != "default")
-                    MouseRegion(
-                      onEnter: (_) {
-                        setState(() {
-                          hoveredOnTrash = true;
-                        });
-                      },
-                      onExit: (_) {
-                        setState(() {
-                          hoveredOnTrash = false;
-                        });
-                      },
-                      child: RawMaterialButton(
-                        hoverColor: Theme.of(context)
-                            .extension<StackColors>()!
-                            .textFieldDefaultBG,
-                        shape: RoundedRectangleBorder(
-                          borderRadius: BorderRadius.circular(
-                            1000,
-                          ),
-                        ),
-                        onPressed: () {
-                          final contact = ref
-                              .read(addressBookServiceProvider)
-                              .getContactById(widget.contactId);
-
-                          // pop context menu
-                          Navigator.of(context).pop();
-
-                          showDialog<dynamic>(
-                            context: context,
-                            useSafeArea: true,
-                            barrierDismissible: true,
-                            builder: (_) => DesktopDialog(
-                              maxWidth: 500,
-                              maxHeight: 300,
-                              child: Column(
-                                children: [
-                                  Row(
-                                    mainAxisAlignment:
-                                        MainAxisAlignment.spaceBetween,
-                                    children: [
-                                      Padding(
-                                        padding: const EdgeInsets.only(
-                                          left: 32,
-                                        ),
-                                        child: Text(
-                                          "Delete ${contact.name}?",
-                                          style: STextStyles.desktopH3(context),
-                                        ),
-                                      ),
-                                      const DesktopDialogCloseButton(),
-                                    ],
-                                  ),
-                                  Expanded(
-                                    child: Padding(
-                                      padding: const EdgeInsets.only(
-                                        left: 32,
-                                        right: 32,
-                                        bottom: 32,
-                                      ),
-                                      child: Column(
-                                        crossAxisAlignment:
-                                            CrossAxisAlignment.start,
-                                        children: [
-                                          const Spacer(
-                                            flex: 1,
-                                          ),
-                                          Text(
-                                            "Contact will be deleted permanently!",
-                                            style: STextStyles.desktopTextSmall(
-                                                context),
-                                          ),
-                                          const Spacer(
-                                            flex: 2,
-                                          ),
-                                          Row(
-                                            children: [
-                                              Expanded(
-                                                child: SecondaryButton(
-                                                  label: "Cancel",
-                                                  onPressed:
-                                                      Navigator.of(context).pop,
-                                                  buttonHeight: ButtonHeight.l,
-                                                ),
-                                              ),
-                                              const SizedBox(
-                                                width: 16,
-                                              ),
-                                              Expanded(
-                                                child: Consumer(
-                                                  builder: (context, ref, __) =>
-                                                      PrimaryButton(
-                                                    label: "Delete",
-                                                    buttonHeight:
-                                                        ButtonHeight.l,
-                                                    onPressed: () {
-                                                      ref
-                                                          .read(
-                                                              addressBookServiceProvider)
-                                                          .removeContact(
-                                                              contact.id);
-                                                      Navigator.of(context)
-                                                          .pop();
-                                                      showFloatingFlushBar(
-                                                        type: FlushBarType
-                                                            .success,
-                                                        message:
-                                                            "${contact.name} deleted",
-                                                        context: context,
-                                                      );
-                                                    },
-                                                  ),
-                                                ),
-                                              ),
-                                            ],
-                                          )
-                                        ],
-                                      ),
-                                    ),
-                                  ),
-                                ],
-                              ),
-                            ),
-                          );
-                        },
-                        child: Padding(
-                          padding: const EdgeInsets.symmetric(
-                            horizontal: 25,
-                            vertical: 16,
-                          ),
-                          child: Row(
-                            children: [
-                              SvgPicture.asset(
-                                Assets.svg.trash,
-                                width: 24,
-                                height: 22,
-                                color: hoveredOnTrash
-                                    ? Theme.of(context)
-                                        .extension<StackColors>()!
-                                        .textDark
-                                    : Theme.of(context)
-                                        .extension<StackColors>()!
-                                        .textFieldDefaultSearchIconLeft,
-                              ),
-                              const SizedBox(
-                                width: 12,
-                              ),
-                              Text(
-                                "Delete contact",
-                                style: STextStyles.desktopTextExtraExtraSmall(
-                                        context)
-                                    .copyWith(
-                                  color: Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textDark,
-                                ),
-                              )
-                            ],
-                          ),
-                        ),
-                      ),
-                    ),
-                ],
-              ),
-            ),
-          ),
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_options_menu_popup.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_options_menu_popup.dart
new file mode 100644
index 000000000..88bd6abf0
--- /dev/null
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_options_menu_popup.dart
@@ -0,0 +1,366 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:stackwallet/notifications/show_flush_bar.dart';
+import 'package:stackwallet/providers/global/address_book_service_provider.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+
+class DesktopContactOptionsMenuPopup extends ConsumerStatefulWidget {
+  const DesktopContactOptionsMenuPopup({Key? key, required this.contactId})
+      : super(key: key);
+
+  final String contactId;
+
+  @override
+  ConsumerState<DesktopContactOptionsMenuPopup> createState() =>
+      _DesktopContactOptionsMenuPopupState();
+}
+
+class _DesktopContactOptionsMenuPopupState
+    extends ConsumerState<DesktopContactOptionsMenuPopup> {
+  bool hoveredOnStar = false;
+  bool hoveredOnPencil = false;
+  bool hoveredOnTrash = false;
+
+  @override
+  Widget build(BuildContext context) {
+    return Stack(
+      children: [
+        Positioned(
+          top: 210,
+          left: MediaQuery.of(context).size.width - 280,
+          child: Container(
+            width: 270,
+            decoration: BoxDecoration(
+              color: Theme.of(context).extension<StackColors>()!.popupBG,
+              borderRadius: BorderRadius.circular(
+                20,
+              ),
+              boxShadow: [
+                Theme.of(context).extension<StackColors>()!.standardBoxShadow,
+              ],
+            ),
+            child: Padding(
+              padding: const EdgeInsets.all(16),
+              child: Column(
+                children: [
+                  MouseRegion(
+                    onEnter: (_) {
+                      setState(() {
+                        hoveredOnStar = true;
+                      });
+                    },
+                    onExit: (_) {
+                      setState(() {
+                        hoveredOnStar = false;
+                      });
+                    },
+                    child: RawMaterialButton(
+                      hoverColor: Theme.of(context)
+                          .extension<StackColors>()!
+                          .textFieldDefaultBG,
+                      shape: RoundedRectangleBorder(
+                        borderRadius: BorderRadius.circular(
+                          1000,
+                        ),
+                      ),
+                      onPressed: () {
+                        final contact =
+                            ref.read(addressBookServiceProvider).getContactById(
+                                  widget.contactId,
+                                );
+                        ref.read(addressBookServiceProvider).editContact(
+                              contact.copyWith(
+                                isFavorite: !contact.isFavorite,
+                              ),
+                            );
+                      },
+                      child: Padding(
+                        padding: const EdgeInsets.symmetric(
+                          horizontal: 25,
+                          vertical: 16,
+                        ),
+                        child: Row(
+                          children: [
+                            SvgPicture.asset(
+                              Assets.svg.star,
+                              width: 24,
+                              height: 22,
+                              color: hoveredOnStar
+                                  ? Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark
+                                  : Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textFieldDefaultSearchIconLeft,
+                            ),
+                            const SizedBox(
+                              width: 12,
+                            ),
+                            Text(
+                              ref.watch(addressBookServiceProvider.select(
+                                      (value) => value
+                                          .getContactById(widget.contactId)
+                                          .isFavorite))
+                                  ? "Remove from favorites"
+                                  : "Add to favorites",
+                              style: STextStyles.desktopTextExtraExtraSmall(
+                                      context)
+                                  .copyWith(
+                                color: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textDark,
+                              ),
+                            )
+                          ],
+                        ),
+                      ),
+                    ),
+                  ),
+                  if (widget.contactId != "default")
+                    const SizedBox(
+                      height: 2,
+                    ),
+                  if (widget.contactId != "default")
+                    MouseRegion(
+                      onEnter: (_) {
+                        setState(() {
+                          hoveredOnPencil = true;
+                        });
+                      },
+                      onExit: (_) {
+                        setState(() {
+                          hoveredOnPencil = false;
+                        });
+                      },
+                      child: RawMaterialButton(
+                        hoverColor: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textFieldDefaultBG,
+                        shape: RoundedRectangleBorder(
+                          borderRadius: BorderRadius.circular(
+                            1000,
+                          ),
+                        ),
+                        onPressed: () {
+                          print("should go to edit");
+                        },
+                        child: Padding(
+                          padding: const EdgeInsets.symmetric(
+                            horizontal: 25,
+                            vertical: 16,
+                          ),
+                          child: Row(
+                            children: [
+                              SvgPicture.asset(
+                                Assets.svg.pencil,
+                                width: 24,
+                                height: 22,
+                                color: hoveredOnPencil
+                                    ? Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textDark
+                                    : Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textFieldDefaultSearchIconLeft,
+                              ),
+                              const SizedBox(
+                                width: 12,
+                              ),
+                              Text(
+                                "Edit contact",
+                                style: STextStyles.desktopTextExtraExtraSmall(
+                                        context)
+                                    .copyWith(
+                                  color: Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark,
+                                ),
+                              )
+                            ],
+                          ),
+                        ),
+                      ),
+                    ),
+                  if (widget.contactId != "default")
+                    const SizedBox(
+                      height: 2,
+                    ),
+                  if (widget.contactId != "default")
+                    MouseRegion(
+                      onEnter: (_) {
+                        setState(() {
+                          hoveredOnTrash = true;
+                        });
+                      },
+                      onExit: (_) {
+                        setState(() {
+                          hoveredOnTrash = false;
+                        });
+                      },
+                      child: RawMaterialButton(
+                        hoverColor: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textFieldDefaultBG,
+                        shape: RoundedRectangleBorder(
+                          borderRadius: BorderRadius.circular(
+                            1000,
+                          ),
+                        ),
+                        onPressed: () {
+                          final contact = ref
+                              .read(addressBookServiceProvider)
+                              .getContactById(widget.contactId);
+
+                          // pop context menu
+                          Navigator.of(context).pop();
+
+                          showDialog<dynamic>(
+                            context: context,
+                            useSafeArea: true,
+                            barrierDismissible: true,
+                            builder: (_) => DesktopDialog(
+                              maxWidth: 500,
+                              maxHeight: 300,
+                              child: Column(
+                                children: [
+                                  Row(
+                                    mainAxisAlignment:
+                                        MainAxisAlignment.spaceBetween,
+                                    children: [
+                                      Padding(
+                                        padding: const EdgeInsets.only(
+                                          left: 32,
+                                        ),
+                                        child: Text(
+                                          "Delete ${contact.name}?",
+                                          style: STextStyles.desktopH3(context),
+                                        ),
+                                      ),
+                                      const DesktopDialogCloseButton(),
+                                    ],
+                                  ),
+                                  Expanded(
+                                    child: Padding(
+                                      padding: const EdgeInsets.only(
+                                        left: 32,
+                                        right: 32,
+                                        bottom: 32,
+                                      ),
+                                      child: Column(
+                                        crossAxisAlignment:
+                                            CrossAxisAlignment.start,
+                                        children: [
+                                          const Spacer(
+                                            flex: 1,
+                                          ),
+                                          Text(
+                                            "Contact will be deleted permanently!",
+                                            style: STextStyles.desktopTextSmall(
+                                                context),
+                                          ),
+                                          const Spacer(
+                                            flex: 2,
+                                          ),
+                                          Row(
+                                            children: [
+                                              Expanded(
+                                                child: SecondaryButton(
+                                                  label: "Cancel",
+                                                  onPressed:
+                                                      Navigator.of(context).pop,
+                                                  buttonHeight: ButtonHeight.l,
+                                                ),
+                                              ),
+                                              const SizedBox(
+                                                width: 16,
+                                              ),
+                                              Expanded(
+                                                child: Consumer(
+                                                  builder: (context, ref, __) =>
+                                                      PrimaryButton(
+                                                    label: "Delete",
+                                                    buttonHeight:
+                                                        ButtonHeight.l,
+                                                    onPressed: () {
+                                                      ref
+                                                          .read(
+                                                              addressBookServiceProvider)
+                                                          .removeContact(
+                                                              contact.id);
+                                                      Navigator.of(context)
+                                                          .pop();
+                                                      showFloatingFlushBar(
+                                                        type: FlushBarType
+                                                            .success,
+                                                        message:
+                                                            "${contact.name} deleted",
+                                                        context: context,
+                                                      );
+                                                    },
+                                                  ),
+                                                ),
+                                              ),
+                                            ],
+                                          )
+                                        ],
+                                      ),
+                                    ),
+                                  ),
+                                ],
+                              ),
+                            ),
+                          );
+                        },
+                        child: Padding(
+                          padding: const EdgeInsets.symmetric(
+                            horizontal: 25,
+                            vertical: 16,
+                          ),
+                          child: Row(
+                            children: [
+                              SvgPicture.asset(
+                                Assets.svg.trash,
+                                width: 24,
+                                height: 22,
+                                color: hoveredOnTrash
+                                    ? Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textDark
+                                    : Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textFieldDefaultSearchIconLeft,
+                              ),
+                              const SizedBox(
+                                width: 12,
+                              ),
+                              Text(
+                                "Delete contact",
+                                style: STextStyles.desktopTextExtraExtraSmall(
+                                        context)
+                                    .copyWith(
+                                  color: Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark,
+                                ),
+                              )
+                            ],
+                          ),
+                        ),
+                      ),
+                    ),
+                ],
+              ),
+            ),
+          ),
+        ),
+      ],
+    );
+  }
+}

From d4b7ec0f174101e406796f4a2bc6162a0c9f0f58 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 09:54:26 -0600
Subject: [PATCH 035/100] desktop edit contact

---
 .../edit_contact_name_emoji_view.dart         | 576 ++++++++++--------
 .../desktop_contact_options_menu_popup.dart   | 252 ++++----
 2 files changed, 462 insertions(+), 366 deletions(-)

diff --git a/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart b/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart
index fff01eee3..a9b264b3c 100644
--- a/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart
+++ b/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart
@@ -1,3 +1,5 @@
+import 'dart:async';
+
 import 'package:emojis/emoji.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -7,14 +9,17 @@ import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/emoji_select_sheet.dart';
 import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 import 'package:stackwallet/widgets/textfield_icon_button.dart';
 
-import 'package:stackwallet/utilities/util.dart';
-
 class EditContactNameEmojiView extends ConsumerStatefulWidget {
   const EditContactNameEmojiView({
     Key? key,
@@ -69,268 +74,323 @@ class _EditContactNameEmojiViewState
     final contact = ref.watch(addressBookServiceProvider
         .select((value) => value.getContactById(contactId)));
 
-    return Scaffold(
-      backgroundColor: Theme.of(context).extension<StackColors>()!.background,
-      appBar: AppBar(
-        leading: AppBarBackButton(
-          onPressed: () async {
-            if (FocusScope.of(context).hasFocus) {
-              FocusScope.of(context).unfocus();
-              await Future<void>.delayed(const Duration(milliseconds: 75));
-            }
-            if (mounted) {
-              Navigator.of(context).pop();
-            }
-          },
-        ),
-        title: Text(
-          "Edit contact",
-          style: STextStyles.navBarTitle(context),
-        ),
-      ),
-      body: LayoutBuilder(
-        builder: (context, constraints) {
-          return Padding(
-            padding: const EdgeInsets.only(
-              left: 12,
-              top: 12,
-              right: 12,
-            ),
-            child: SingleChildScrollView(
-              child: ConstrainedBox(
-                constraints: BoxConstraints(
-                  minHeight: constraints.maxHeight - 24,
-                ),
-                child: IntrinsicHeight(
-                  child: Padding(
-                    padding: const EdgeInsets.all(4),
-                    child: Column(
-                      children: [
-                        GestureDetector(
-                          onTap: () {
-                            if (_selectedEmoji != null) {
-                              setState(() {
-                                _selectedEmoji = null;
-                              });
-                              return;
-                            }
-                            showModalBottomSheet<dynamic>(
-                              backgroundColor: Colors.transparent,
-                              context: context,
-                              shape: const RoundedRectangleBorder(
-                                borderRadius: BorderRadius.vertical(
-                                  top: Radius.circular(20),
-                                ),
-                              ),
-                              builder: (_) => const EmojiSelectSheet(),
-                            ).then((value) {
-                              if (value is Emoji) {
-                                setState(() {
-                                  _selectedEmoji = value;
-                                });
-                              }
-                            });
-                          },
-                          child: SizedBox(
-                            height: 48,
-                            width: 48,
-                            child: Stack(
-                              children: [
-                                Container(
-                                  height: 48,
-                                  width: 48,
-                                  decoration: BoxDecoration(
-                                    borderRadius: BorderRadius.circular(24),
-                                    color: Theme.of(context)
-                                        .extension<StackColors>()!
-                                        .textFieldActiveBG,
-                                  ),
-                                  child: Center(
-                                    child: _selectedEmoji == null
-                                        ? SvgPicture.asset(
-                                            Assets.svg.user,
-                                            height: 24,
-                                            width: 24,
-                                          )
-                                        : Text(
-                                            _selectedEmoji!.char,
-                                            style: STextStyles.pageTitleH1(
-                                                context),
-                                          ),
-                                  ),
-                                ),
-                                Align(
-                                  alignment: Alignment.bottomRight,
-                                  child: Container(
-                                    height: 14,
-                                    width: 14,
-                                    decoration: BoxDecoration(
-                                        borderRadius: BorderRadius.circular(14),
-                                        color: Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .accentColorDark),
-                                    child: Center(
-                                      child: _selectedEmoji == null
-                                          ? SvgPicture.asset(
-                                              Assets.svg.plus,
-                                              color: Theme.of(context)
-                                                  .extension<StackColors>()!
-                                                  .textWhite,
-                                              width: 12,
-                                              height: 12,
-                                            )
-                                          : SvgPicture.asset(
-                                              Assets.svg.thickX,
-                                              color: Theme.of(context)
-                                                  .extension<StackColors>()!
-                                                  .textWhite,
-                                              width: 8,
-                                              height: 8,
-                                            ),
-                                    ),
-                                  ),
-                                )
-                              ],
-                            ),
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 8,
-                        ),
-                        ClipRRect(
-                          borderRadius: BorderRadius.circular(
-                            Constants.size.circularBorderRadius,
-                          ),
-                          child: TextField(
-                            autocorrect: Util.isDesktop ? false : true,
-                            enableSuggestions: Util.isDesktop ? false : true,
-                            controller: nameController,
-                            focusNode: nameFocusNode,
-                            style: STextStyles.field(context),
-                            onChanged: (_) => setState(() {}),
-                            decoration: standardInputDecoration(
-                              "Enter contact name",
-                              nameFocusNode,
-                              context,
-                            ).copyWith(
-                              suffixIcon: nameController.text.isNotEmpty
-                                  ? Padding(
-                                      padding: const EdgeInsets.only(right: 0),
-                                      child: UnconstrainedBox(
-                                        child: Row(
-                                          children: [
-                                            TextFieldIconButton(
-                                              child: const XIcon(),
-                                              onTap: () async {
-                                                setState(() {
-                                                  nameController.text = "";
-                                                });
-                                              },
-                                            ),
-                                          ],
-                                        ),
-                                      ),
-                                    )
-                                  : null,
-                            ),
-                          ),
-                        ),
-                        const Spacer(),
-                        const SizedBox(
-                          height: 16,
-                        ),
-                        Row(
-                          children: [
-                            Expanded(
-                              child: TextButton(
-                                style: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .getSecondaryEnabledButtonColor(context),
-                                child: Text(
-                                  "Cancel",
-                                  style: STextStyles.button(context).copyWith(
-                                      color: Theme.of(context)
-                                          .extension<StackColors>()!
-                                          .accentColorDark),
-                                ),
-                                onPressed: () async {
-                                  if (FocusScope.of(context).hasFocus) {
-                                    FocusScope.of(context).unfocus();
-                                    await Future<void>.delayed(
-                                        const Duration(milliseconds: 75));
-                                  }
-                                  if (mounted) {
-                                    Navigator.of(context).pop();
-                                  }
-                                },
-                              ),
-                            ),
-                            const SizedBox(
-                              width: 16,
-                            ),
-                            Expanded(
-                              child: Builder(
-                                builder: (context) {
-                                  bool shouldEnableSave =
-                                      nameController.text.isNotEmpty;
+    final isDesktop = Util.isDesktop;
+    final double emojiSize = isDesktop ? 56 : 48;
 
-                                  return TextButton(
-                                    style: shouldEnableSave
-                                        ? Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .getPrimaryEnabledButtonColor(
-                                                context)
-                                        : Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .getPrimaryDisabledButtonColor(
-                                                context),
-                                    onPressed: shouldEnableSave
-                                        ? () async {
-                                            if (FocusScope.of(context)
-                                                .hasFocus) {
-                                              FocusScope.of(context).unfocus();
-                                              await Future<void>.delayed(
-                                                const Duration(
-                                                    milliseconds: 75),
-                                              );
-                                            }
-                                            final editedContact =
-                                                contact.copyWith(
-                                              shouldCopyEmojiWithNull: true,
-                                              name: nameController.text,
-                                              emojiChar: _selectedEmoji == null
-                                                  ? null
-                                                  : _selectedEmoji!.char,
-                                            );
-                                            ref
-                                                .read(
-                                                    addressBookServiceProvider)
-                                                .editContact(
-                                                  editedContact,
-                                                );
-                                            if (mounted) {
-                                              Navigator.of(context).pop();
-                                            }
-                                          }
-                                        : null,
-                                    child: Text(
-                                      "Save",
-                                      style: STextStyles.button(context),
-                                    ),
-                                  );
-                                },
-                              ),
-                            ),
-                          ],
-                        )
-                      ],
+    return ConditionalParent(
+      condition: !isDesktop,
+      builder: (child) => Scaffold(
+        backgroundColor: Theme.of(context).extension<StackColors>()!.background,
+        appBar: AppBar(
+          leading: AppBarBackButton(
+            onPressed: () async {
+              if (FocusScope.of(context).hasFocus) {
+                FocusScope.of(context).unfocus();
+                await Future<void>.delayed(const Duration(milliseconds: 75));
+              }
+              if (mounted) {
+                Navigator.of(context).pop();
+              }
+            },
+          ),
+          title: Text(
+            "Edit contact",
+            style: STextStyles.navBarTitle(context),
+          ),
+        ),
+        body: LayoutBuilder(
+          builder: (context, constraints) {
+            return Padding(
+              padding: const EdgeInsets.only(
+                left: 12,
+                top: 12,
+                right: 12,
+              ),
+              child: SingleChildScrollView(
+                child: ConstrainedBox(
+                  constraints: BoxConstraints(
+                    minHeight: constraints.maxHeight - 24,
+                  ),
+                  child: IntrinsicHeight(
+                    child: Padding(
+                      padding: const EdgeInsets.all(4),
+                      child: child,
                     ),
                   ),
                 ),
               ),
+            );
+          },
+        ),
+      ),
+      child: Column(
+        children: [
+          Row(
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: [
+              GestureDetector(
+                onTap: () {
+                  if (_selectedEmoji != null) {
+                    setState(() {
+                      _selectedEmoji = null;
+                    });
+                    return;
+                  }
+                  if (isDesktop) {
+                    showDialog<dynamic>(
+                        barrierColor: Colors.transparent,
+                        context: context,
+                        builder: (context) {
+                          return const DesktopDialog(
+                            maxHeight: 700,
+                            maxWidth: 600,
+                            child: Padding(
+                              padding: EdgeInsets.only(
+                                left: 32,
+                                right: 20,
+                                top: 32,
+                                bottom: 32,
+                              ),
+                              child: EmojiSelectSheet(),
+                            ),
+                          );
+                        }).then((value) {
+                      if (value is Emoji) {
+                        setState(() {
+                          _selectedEmoji = value;
+                        });
+                      }
+                    });
+                  } else {
+                    showModalBottomSheet<dynamic>(
+                      backgroundColor: Colors.transparent,
+                      context: context,
+                      shape: const RoundedRectangleBorder(
+                        borderRadius: BorderRadius.vertical(
+                          top: Radius.circular(20),
+                        ),
+                      ),
+                      builder: (_) => const EmojiSelectSheet(),
+                    ).then((value) {
+                      if (value is Emoji) {
+                        setState(() {
+                          _selectedEmoji = value;
+                        });
+                      }
+                    });
+                  }
+                },
+                child: SizedBox(
+                  height: emojiSize,
+                  width: emojiSize,
+                  child: Stack(
+                    children: [
+                      Container(
+                        height: emojiSize,
+                        width: emojiSize,
+                        decoration: BoxDecoration(
+                          borderRadius: BorderRadius.circular(emojiSize / 2),
+                          color: Theme.of(context)
+                              .extension<StackColors>()!
+                              .textFieldActiveBG,
+                        ),
+                        child: Center(
+                          child: _selectedEmoji == null
+                              ? SvgPicture.asset(
+                                  Assets.svg.user,
+                                  height: emojiSize / 2,
+                                  width: emojiSize / 2,
+                                )
+                              : Text(
+                                  _selectedEmoji!.char,
+                                  style: isDesktop
+                                      ? STextStyles.desktopH3(context)
+                                      : STextStyles.pageTitleH1(context),
+                                ),
+                        ),
+                      ),
+                      Align(
+                        alignment: Alignment.bottomRight,
+                        child: Container(
+                          height: 14,
+                          width: 14,
+                          decoration: BoxDecoration(
+                              borderRadius: BorderRadius.circular(14),
+                              color: Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .accentColorDark),
+                          child: Center(
+                            child: _selectedEmoji == null
+                                ? SvgPicture.asset(
+                                    Assets.svg.plus,
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textWhite,
+                                    width: 12,
+                                    height: 12,
+                                  )
+                                : SvgPicture.asset(
+                                    Assets.svg.thickX,
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textWhite,
+                                    width: 8,
+                                    height: 8,
+                                  ),
+                          ),
+                        ),
+                      )
+                    ],
+                  ),
+                ),
+              ),
+              if (isDesktop)
+                const SizedBox(
+                  width: 8,
+                ),
+              if (isDesktop)
+                Expanded(
+                  child: ClipRRect(
+                    borderRadius: BorderRadius.circular(
+                      Constants.size.circularBorderRadius,
+                    ),
+                    child: TextField(
+                      autocorrect: Util.isDesktop ? false : true,
+                      enableSuggestions: Util.isDesktop ? false : true,
+                      controller: nameController,
+                      focusNode: nameFocusNode,
+                      style: STextStyles.field(context),
+                      onChanged: (_) => setState(() {}),
+                      decoration: standardInputDecoration(
+                        "Enter contact name",
+                        nameFocusNode,
+                        context,
+                      ).copyWith(
+                        suffixIcon: nameController.text.isNotEmpty
+                            ? Padding(
+                                padding: const EdgeInsets.only(right: 0),
+                                child: UnconstrainedBox(
+                                  child: Row(
+                                    children: [
+                                      TextFieldIconButton(
+                                        child: const XIcon(),
+                                        onTap: () async {
+                                          setState(() {
+                                            nameController.text = "";
+                                          });
+                                        },
+                                      ),
+                                    ],
+                                  ),
+                                ),
+                              )
+                            : null,
+                      ),
+                    ),
+                  ),
+                ),
+            ],
+          ),
+          if (!isDesktop)
+            const SizedBox(
+              height: 8,
             ),
-          );
-        },
+          if (!isDesktop)
+            ClipRRect(
+              borderRadius: BorderRadius.circular(
+                Constants.size.circularBorderRadius,
+              ),
+              child: TextField(
+                autocorrect: Util.isDesktop ? false : true,
+                enableSuggestions: Util.isDesktop ? false : true,
+                controller: nameController,
+                focusNode: nameFocusNode,
+                style: STextStyles.field(context),
+                onChanged: (_) => setState(() {}),
+                decoration: standardInputDecoration(
+                  "Enter contact name",
+                  nameFocusNode,
+                  context,
+                ).copyWith(
+                  suffixIcon: nameController.text.isNotEmpty
+                      ? Padding(
+                          padding: const EdgeInsets.only(right: 0),
+                          child: UnconstrainedBox(
+                            child: Row(
+                              children: [
+                                TextFieldIconButton(
+                                  child: const XIcon(),
+                                  onTap: () async {
+                                    setState(() {
+                                      nameController.text = "";
+                                    });
+                                  },
+                                ),
+                              ],
+                            ),
+                          ),
+                        )
+                      : null,
+                ),
+              ),
+            ),
+          const Spacer(),
+          const SizedBox(
+            height: 16,
+          ),
+          Row(
+            children: [
+              Expanded(
+                child: SecondaryButton(
+                  label: "Cancel",
+                  buttonHeight: isDesktop ? ButtonHeight.l : null,
+                  onPressed: () async {
+                    if (!isDesktop && FocusScope.of(context).hasFocus) {
+                      FocusScope.of(context).unfocus();
+                      await Future<void>.delayed(
+                          const Duration(milliseconds: 75));
+                    }
+                    if (mounted) {
+                      Navigator.of(context).pop();
+                    }
+                  },
+                ),
+              ),
+              const SizedBox(
+                width: 16,
+              ),
+              Expanded(
+                child: PrimaryButton(
+                  label: "Save",
+                  enabled: nameController.text.isNotEmpty,
+                  buttonHeight: isDesktop ? ButtonHeight.l : null,
+                  onPressed: () async {
+                    if (!isDesktop && FocusScope.of(context).hasFocus) {
+                      FocusScope.of(context).unfocus();
+                      await Future<void>.delayed(
+                        const Duration(milliseconds: 75),
+                      );
+                    }
+                    final editedContact = contact.copyWith(
+                      shouldCopyEmojiWithNull: true,
+                      name: nameController.text,
+                      emojiChar:
+                          _selectedEmoji == null ? null : _selectedEmoji!.char,
+                    );
+                    unawaited(
+                      ref.read(addressBookServiceProvider).editContact(
+                            editedContact,
+                          ),
+                    );
+                    if (mounted) {
+                      Navigator.of(context).pop();
+                    }
+                  },
+                ),
+              ),
+            ],
+          )
+        ],
       ),
     );
   }
diff --git a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_options_menu_popup.dart b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_options_menu_popup.dart
index 88bd6abf0..690d1be98 100644
--- a/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_options_menu_popup.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/subwidgets/desktop_contact_options_menu_popup.dart
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 import 'package:stackwallet/notifications/show_flush_bar.dart';
+import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart';
 import 'package:stackwallet/providers/global/address_book_service_provider.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
@@ -28,6 +29,147 @@ class _DesktopContactOptionsMenuPopupState
   bool hoveredOnPencil = false;
   bool hoveredOnTrash = false;
 
+  void editContact() {
+    // pop context menu
+    Navigator.of(context).pop();
+
+    showDialog<dynamic>(
+      context: context,
+      useSafeArea: true,
+      barrierDismissible: true,
+      builder: (_) => DesktopDialog(
+        maxWidth: 580,
+        maxHeight: 400,
+        child: Column(
+          children: [
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Padding(
+                  padding: const EdgeInsets.only(
+                    left: 32,
+                  ),
+                  child: Text(
+                    "Edit contact",
+                    style: STextStyles.desktopH3(context),
+                  ),
+                ),
+                const DesktopDialogCloseButton(),
+              ],
+            ),
+            Expanded(
+              child: Padding(
+                padding: const EdgeInsets.only(
+                  top: 16,
+                  left: 32,
+                  right: 32,
+                  bottom: 32,
+                ),
+                child: EditContactNameEmojiView(
+                  contactId: widget.contactId,
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  void attemptDeleteContact() {
+    final contact =
+        ref.read(addressBookServiceProvider).getContactById(widget.contactId);
+
+    // pop context menu
+    Navigator.of(context).pop();
+
+    showDialog<dynamic>(
+      context: context,
+      useSafeArea: true,
+      barrierDismissible: true,
+      builder: (_) => DesktopDialog(
+        maxWidth: 500,
+        maxHeight: 400,
+        child: Column(
+          children: [
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Padding(
+                  padding: const EdgeInsets.only(
+                    left: 32,
+                  ),
+                  child: Text(
+                    "Delete ${contact.name}?",
+                    style: STextStyles.desktopH3(context),
+                  ),
+                ),
+                const DesktopDialogCloseButton(),
+              ],
+            ),
+            Expanded(
+              child: Padding(
+                padding: const EdgeInsets.only(
+                  left: 32,
+                  right: 32,
+                  bottom: 32,
+                ),
+                child: Column(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: [
+                    const Spacer(
+                      flex: 1,
+                    ),
+                    Text(
+                      "Contact will be deleted permanently!",
+                      style: STextStyles.desktopTextSmall(context),
+                    ),
+                    const Spacer(
+                      flex: 2,
+                    ),
+                    Row(
+                      children: [
+                        Expanded(
+                          child: SecondaryButton(
+                            label: "Cancel",
+                            onPressed: Navigator.of(context).pop,
+                            buttonHeight: ButtonHeight.l,
+                          ),
+                        ),
+                        const SizedBox(
+                          width: 16,
+                        ),
+                        Expanded(
+                          child: Consumer(
+                            builder: (context, ref, __) => PrimaryButton(
+                              label: "Delete",
+                              buttonHeight: ButtonHeight.l,
+                              onPressed: () {
+                                ref
+                                    .read(addressBookServiceProvider)
+                                    .removeContact(contact.id);
+                                Navigator.of(context).pop();
+                                showFloatingFlushBar(
+                                  type: FlushBarType.success,
+                                  message: "${contact.name} deleted",
+                                  context: context,
+                                );
+                              },
+                            ),
+                          ),
+                        ),
+                      ],
+                    )
+                  ],
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
   @override
   Widget build(BuildContext context) {
     return Stack(
@@ -148,9 +290,7 @@ class _DesktopContactOptionsMenuPopupState
                             1000,
                           ),
                         ),
-                        onPressed: () {
-                          print("should go to edit");
-                        },
+                        onPressed: editContact,
                         child: Padding(
                           padding: const EdgeInsets.symmetric(
                             horizontal: 25,
@@ -213,111 +353,7 @@ class _DesktopContactOptionsMenuPopupState
                             1000,
                           ),
                         ),
-                        onPressed: () {
-                          final contact = ref
-                              .read(addressBookServiceProvider)
-                              .getContactById(widget.contactId);
-
-                          // pop context menu
-                          Navigator.of(context).pop();
-
-                          showDialog<dynamic>(
-                            context: context,
-                            useSafeArea: true,
-                            barrierDismissible: true,
-                            builder: (_) => DesktopDialog(
-                              maxWidth: 500,
-                              maxHeight: 300,
-                              child: Column(
-                                children: [
-                                  Row(
-                                    mainAxisAlignment:
-                                        MainAxisAlignment.spaceBetween,
-                                    children: [
-                                      Padding(
-                                        padding: const EdgeInsets.only(
-                                          left: 32,
-                                        ),
-                                        child: Text(
-                                          "Delete ${contact.name}?",
-                                          style: STextStyles.desktopH3(context),
-                                        ),
-                                      ),
-                                      const DesktopDialogCloseButton(),
-                                    ],
-                                  ),
-                                  Expanded(
-                                    child: Padding(
-                                      padding: const EdgeInsets.only(
-                                        left: 32,
-                                        right: 32,
-                                        bottom: 32,
-                                      ),
-                                      child: Column(
-                                        crossAxisAlignment:
-                                            CrossAxisAlignment.start,
-                                        children: [
-                                          const Spacer(
-                                            flex: 1,
-                                          ),
-                                          Text(
-                                            "Contact will be deleted permanently!",
-                                            style: STextStyles.desktopTextSmall(
-                                                context),
-                                          ),
-                                          const Spacer(
-                                            flex: 2,
-                                          ),
-                                          Row(
-                                            children: [
-                                              Expanded(
-                                                child: SecondaryButton(
-                                                  label: "Cancel",
-                                                  onPressed:
-                                                      Navigator.of(context).pop,
-                                                  buttonHeight: ButtonHeight.l,
-                                                ),
-                                              ),
-                                              const SizedBox(
-                                                width: 16,
-                                              ),
-                                              Expanded(
-                                                child: Consumer(
-                                                  builder: (context, ref, __) =>
-                                                      PrimaryButton(
-                                                    label: "Delete",
-                                                    buttonHeight:
-                                                        ButtonHeight.l,
-                                                    onPressed: () {
-                                                      ref
-                                                          .read(
-                                                              addressBookServiceProvider)
-                                                          .removeContact(
-                                                              contact.id);
-                                                      Navigator.of(context)
-                                                          .pop();
-                                                      showFloatingFlushBar(
-                                                        type: FlushBarType
-                                                            .success,
-                                                        message:
-                                                            "${contact.name} deleted",
-                                                        context: context,
-                                                      );
-                                                    },
-                                                  ),
-                                                ),
-                                              ),
-                                            ],
-                                          )
-                                        ],
-                                      ),
-                                    ),
-                                  ),
-                                ],
-                              ),
-                            ),
-                          );
-                        },
+                        onPressed: attemptDeleteContact,
                         child: Padding(
                           padding: const EdgeInsets.symmetric(
                             horizontal: 25,

From 4d17c1db5f732acb00b1726a530125318889f706 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 10:22:34 -0600
Subject: [PATCH 036/100] addressbook filter coins list fix

---
 lib/pages/address_book_views/address_book_view.dart       | 8 ++++----
 .../subviews/address_book_filter_view.dart                | 2 +-
 .../home/address_book_view/desktop_address_book.dart      | 7 ++++---
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/lib/pages/address_book_views/address_book_view.dart b/lib/pages/address_book_views/address_book_view.dart
index cdc9fb5b7..c87906870 100644
--- a/lib/pages/address_book_views/address_book_view.dart
+++ b/lib/pages/address_book_views/address_book_view.dart
@@ -51,8 +51,7 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
     ref.refresh(addressBookFilterProvider);
 
     if (widget.coin == null) {
-      List<Coin> coins =
-          Coin.values.where((e) => !(e == Coin.epicCash)).toList();
+      List<Coin> coins = Coin.values.toList();
       coins.remove(Coin.firoTestNet);
 
       bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins;
@@ -60,8 +59,9 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
       if (showTestNet) {
         ref.read(addressBookFilterProvider).addAll(coins, false);
       } else {
-        ref.read(addressBookFilterProvider).addAll(
-            coins.getRange(0, coins.length - kTestNetCoinCount + 1), false);
+        ref
+            .read(addressBookFilterProvider)
+            .addAll(coins.getRange(0, coins.length - kTestNetCoinCount), false);
       }
     } else {
       ref.read(addressBookFilterProvider).add(widget.coin!, false);
diff --git a/lib/pages/address_book_views/subviews/address_book_filter_view.dart b/lib/pages/address_book_views/subviews/address_book_filter_view.dart
index c129251d5..55c3d47ac 100644
--- a/lib/pages/address_book_views/subviews/address_book_filter_view.dart
+++ b/lib/pages/address_book_views/subviews/address_book_filter_view.dart
@@ -38,7 +38,7 @@ class _AddressBookFilterViewState extends ConsumerState<AddressBookFilterView> {
     } else {
       _coins = coins
           .toList(growable: false)
-          .getRange(0, coins.length - kTestNetCoinCount + 1)
+          .getRange(0, coins.length - kTestNetCoinCount)
           .toList(growable: false);
     }
     super.initState();
diff --git a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
index f028a3424..e5432081c 100644
--- a/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
+++ b/lib/pages_desktop_specific/home/address_book_view/desktop_address_book.dart
@@ -84,7 +84,7 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
     ref.refresh(addressBookFilterProvider);
 
     // if (widget.coin == null) {
-    List<Coin> coins = Coin.values.where((e) => !(e == Coin.epicCash)).toList();
+    List<Coin> coins = Coin.values.toList();
     coins.remove(Coin.firoTestNet);
 
     bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins;
@@ -92,8 +92,9 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
     if (showTestNet) {
       ref.read(addressBookFilterProvider).addAll(coins, false);
     } else {
-      ref.read(addressBookFilterProvider).addAll(
-          coins.getRange(0, coins.length - kTestNetCoinCount + 1), false);
+      ref
+          .read(addressBookFilterProvider)
+          .addAll(coins.getRange(0, coins.length - kTestNetCoinCount), false);
     }
     // } else {
     //   ref.read(addressBookFilterProvider).add(widget.coin!, false);

From 8207474d0973387b9fa7d32d4eb510132b34cc72 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Fri, 18 Nov 2022 09:30:21 -0700
Subject: [PATCH 037/100] ocean breeze selector + functionality added

---
 assets/svg/ocean-breeze-theme.svg             |  28 +++++
 lib/main.dart                                 |   2 +-
 .../settings_menu/appearance_settings.dart    | 105 +++++++++++++++++-
 lib/utilities/assets.dart                     |   1 +
 pubspec.yaml                                  |   1 +
 5 files changed, 135 insertions(+), 2 deletions(-)
 create mode 100644 assets/svg/ocean-breeze-theme.svg

diff --git a/assets/svg/ocean-breeze-theme.svg b/assets/svg/ocean-breeze-theme.svg
new file mode 100644
index 000000000..0deb96ec8
--- /dev/null
+++ b/assets/svg/ocean-breeze-theme.svg
@@ -0,0 +1,28 @@
+<svg width="200" height="162" viewBox="0 0 200 162" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_518_22068)">
+<rect width="200" height="162" rx="8" fill="url(#paint0_linear_518_22068)"/>
+<rect x="10" y="10" width="180" height="20" rx="2" fill="#C2DAE2"/>
+<rect x="16" y="16" width="106" height="8" rx="1" fill="#227386"/>
+<rect x="10" y="40" width="180" height="20" rx="2" fill="#FEFEFE"/>
+<rect x="16" y="46" width="106" height="8" rx="1" fill="#BDD5DB"/>
+<rect x="10" y="62" width="180" height="20" rx="2" fill="#FEFEFE"/>
+<rect x="16" y="68" width="106" height="8" rx="1" fill="#BDD5DB"/>
+<rect x="10" y="84" width="180" height="20" rx="2" fill="#FEFEFE"/>
+<rect x="16" y="90" width="106" height="8" rx="1" fill="#BDD5DB"/>
+<rect x="10" y="106" width="180" height="20" rx="2" fill="#FEFEFE"/>
+<rect x="16" y="112" width="106" height="8" rx="1" fill="#BDD5DB"/>
+<rect x="10" y="128" width="180" height="20" rx="2" fill="#FEFEFE"/>
+<rect x="16" y="134" width="106" height="8" rx="1" fill="#BDD5DB"/>
+<rect x="10" y="150" width="180" height="20" rx="2" fill="#FEFEFE"/>
+<rect x="16" y="156" width="106" height="8" rx="1" fill="#BDD5DB"/>
+</g>
+<defs>
+<linearGradient id="paint0_linear_518_22068" x1="100" y1="0" x2="100" y2="162" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F3F7FA"/>
+<stop offset="1" stop-color="#E8F2F9"/>
+</linearGradient>
+<clipPath id="clip0_518_22068">
+<rect width="200" height="162" rx="8" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/lib/main.dart b/lib/main.dart
index 2d1bab160..66b3bb974 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -77,7 +77,7 @@ void main() async {
 
   if (Util.isDesktop) {
     setWindowTitle('Stack Wallet');
-    setWindowMinSize(const Size(1200, 1100));
+    setWindowMinSize(const Size(1220, 1100));
     setWindowMaxSize(Size.infinite);
   }
 
diff --git a/lib/pages_desktop_specific/home/settings_menu/appearance_settings.dart b/lib/pages_desktop_specific/home/settings_menu/appearance_settings.dart
index 7a9ed557f..bfd5f3b61 100644
--- a/lib/pages_desktop_specific/home/settings_menu/appearance_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/appearance_settings.dart
@@ -10,6 +10,7 @@ import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/color_theme.dart';
 import 'package:stackwallet/utilities/theme/dark_colors.dart';
 import 'package:stackwallet/utilities/theme/light_colors.dart';
+import 'package:stackwallet/utilities/theme/ocean_breeze_colors.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
@@ -291,7 +292,109 @@ class _ThemeToggle extends ConsumerState<ThemeToggle> {
           ),
         ),
         const SizedBox(
-          width: 20,
+          width: 10,
+        ),
+        MaterialButton(
+          splashColor: Colors.transparent,
+          hoverColor: Colors.transparent,
+          padding: const EdgeInsets.all(0),
+          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(
+              Constants.size.circularBorderRadius,
+            ),
+          ),
+          onPressed: () {
+            DB.instance.put<dynamic>(
+              boxName: DB.boxNameTheme,
+              key: "colorScheme",
+              value: ThemeType.oceanBreeze.name,
+            );
+            ref.read(colorThemeProvider.state).state =
+                StackColors.fromStackColorTheme(
+              OceanBreezeColors(),
+            );
+
+            setState(() {
+              _selectedTheme = "oceanBreeze";
+            });
+          },
+          child: SizedBox(
+            width: 200,
+            child: Column(
+              mainAxisSize: MainAxisSize.min,
+              children: [
+                Container(
+                  decoration: BoxDecoration(
+                    border: Border.all(
+                      width: 2.5,
+                      color: _selectedTheme == "oceanBreeze"
+                          ? Theme.of(context)
+                              .extension<StackColors>()!
+                              .infoItemIcons
+                          : Theme.of(context).extension<StackColors>()!.popupBG,
+                    ),
+                    borderRadius: BorderRadius.circular(
+                      Constants.size.circularBorderRadius,
+                    ),
+                  ),
+                  child: SvgPicture.asset(
+                    Assets.svg.themeOcean,
+                  ),
+                ),
+                const SizedBox(
+                  height: 12,
+                ),
+                Row(
+                  children: [
+                    SizedBox(
+                      width: 20,
+                      height: 20,
+                      child: Radio(
+                        activeColor: Theme.of(context)
+                            .extension<StackColors>()!
+                            .radioButtonIconEnabled,
+                        value: "oceanBreeze",
+                        groupValue: _selectedTheme,
+                        onChanged: (newValue) {
+                          if (newValue is String && newValue == "oceanBreeze") {
+                            DB.instance.put<dynamic>(
+                              boxName: DB.boxNameTheme,
+                              key: "colorScheme",
+                              value: ThemeType.oceanBreeze.name,
+                            );
+                            ref.read(colorThemeProvider.state).state =
+                                StackColors.fromStackColorTheme(
+                              OceanBreezeColors(),
+                            );
+
+                            setState(() {
+                              _selectedTheme = "oceanBreeze";
+                            });
+                          }
+                        },
+                      ),
+                    ),
+                    const SizedBox(
+                      width: 14,
+                    ),
+                    Text(
+                      "Ocean Breeze",
+                      style:
+                          STextStyles.desktopTextExtraSmall(context).copyWith(
+                        color: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textDark,
+                      ),
+                    ),
+                  ],
+                ),
+              ],
+            ),
+          ),
+        ),
+        const SizedBox(
+          width: 10,
         ),
         MaterialButton(
           splashColor: Colors.transparent,
diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart
index 38d720969..d7d2ebc6f 100644
--- a/lib/utilities/assets.dart
+++ b/lib/utilities/assets.dart
@@ -59,6 +59,7 @@ class _SVG {
   String txExchangeFailed(BuildContext context) =>
       "assets/svg/${Theme.of(context).extension<StackColors>()!.themeType.name}/tx-exchange-icon-failed.svg";
 
+  String get themeOcean => "assets/svg/ocean-breeze-theme.svg";
   String get circleSliders => "assets/svg/configuration.svg";
   String get circlePlus => "assets/svg/plus-circle.svg";
   String get framedGear => "assets/svg/framed-gear.svg";
diff --git a/pubspec.yaml b/pubspec.yaml
index bba5f6ed2..94670af1a 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -316,6 +316,7 @@ flutter:
     - assets/svg/arrow-down.svg
     - assets/svg/plus-circle.svg
     - assets/svg/configuration.svg
+    - assets/svg/ocean-breeze-theme.svg
     # coin icons
     - assets/svg/coin_icons/Bitcoin.svg
     - assets/svg/coin_icons/Litecoin.svg

From 9508afbd5b84823a264e3c091cab9768292e9e01 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 12:26:27 -0600
Subject: [PATCH 038/100] add ocean breeze specific assets

---
 assets/svg/{dark => }/dark-theme.svg          |  0
 assets/svg/{light => }/light-mode.svg         |  0
 assets/svg/oceanBreeze/bell-new.svg           |  5 ++
 assets/svg/oceanBreeze/buy-coins-icon.svg     | 18 +++++
 assets/svg/oceanBreeze/exchange-2.svg         |  4 +
 assets/svg/oceanBreeze/stack-icon1.svg        |  5 ++
 .../oceanBreeze/tx-exchange-icon-failed.svg   |  7 ++
 .../oceanBreeze/tx-exchange-icon-pending.svg  |  6 ++
 assets/svg/oceanBreeze/tx-exchange-icon.svg   |  4 +
 .../oceanBreeze/tx-icon-receive-failed.svg    |  7 ++
 .../oceanBreeze/tx-icon-receive-pending.svg   |  5 ++
 assets/svg/oceanBreeze/tx-icon-receive.svg    |  4 +
 .../svg/oceanBreeze/tx-icon-send-failed.svg   |  7 ++
 .../svg/oceanBreeze/tx-icon-send-pending.svg  |  6 ++
 assets/svg/oceanBreeze/tx-icon-send.svg       |  4 +
 lib/utilities/assets.dart                     |  5 +-
 pubspec.yaml                                  | 77 ++++++++++++-------
 17 files changed, 135 insertions(+), 29 deletions(-)
 rename assets/svg/{dark => }/dark-theme.svg (100%)
 rename assets/svg/{light => }/light-mode.svg (100%)
 create mode 100644 assets/svg/oceanBreeze/bell-new.svg
 create mode 100644 assets/svg/oceanBreeze/buy-coins-icon.svg
 create mode 100644 assets/svg/oceanBreeze/exchange-2.svg
 create mode 100644 assets/svg/oceanBreeze/stack-icon1.svg
 create mode 100644 assets/svg/oceanBreeze/tx-exchange-icon-failed.svg
 create mode 100644 assets/svg/oceanBreeze/tx-exchange-icon-pending.svg
 create mode 100644 assets/svg/oceanBreeze/tx-exchange-icon.svg
 create mode 100644 assets/svg/oceanBreeze/tx-icon-receive-failed.svg
 create mode 100644 assets/svg/oceanBreeze/tx-icon-receive-pending.svg
 create mode 100644 assets/svg/oceanBreeze/tx-icon-receive.svg
 create mode 100644 assets/svg/oceanBreeze/tx-icon-send-failed.svg
 create mode 100644 assets/svg/oceanBreeze/tx-icon-send-pending.svg
 create mode 100644 assets/svg/oceanBreeze/tx-icon-send.svg

diff --git a/assets/svg/dark/dark-theme.svg b/assets/svg/dark-theme.svg
similarity index 100%
rename from assets/svg/dark/dark-theme.svg
rename to assets/svg/dark-theme.svg
diff --git a/assets/svg/light/light-mode.svg b/assets/svg/light-mode.svg
similarity index 100%
rename from assets/svg/light/light-mode.svg
rename to assets/svg/light-mode.svg
diff --git a/assets/svg/oceanBreeze/bell-new.svg b/assets/svg/oceanBreeze/bell-new.svg
new file mode 100644
index 000000000..8cef32715
--- /dev/null
+++ b/assets/svg/oceanBreeze/bell-new.svg
@@ -0,0 +1,5 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12.5 17.5C12.5 17.9193 12.2383 18.3672 11.7695 18.6797C11.3008 18.9922 10.6289 19.1667 10 19.1667C9.33594 19.1667 8.69922 18.9922 8.23047 18.6797C7.76172 18.3672 7.5 17.9193 7.5 17.5H12.5Z" fill="#227386"/>
+<path d="M11.1903 1.98716V2.67947C13.9059 3.2142 15.9519 5.54245 15.9519 8.33331V9.0112C15.9519 10.7095 16.5955 12.3429 17.7561 13.6122L18.0314 13.9114C18.3439 14.254 18.422 14.7372 18.2286 15.1518C18.0351 15.5665 17.611 15.8333 17.1423 15.8333H2.85739C2.38867 15.8333 1.96351 15.5665 1.77148 15.1518C1.57945 14.7372 1.65626 14.254 1.96771 13.9114L2.24359 13.6122C3.40573 12.3429 4.0478 10.7095 4.0478 9.0112V8.33331C4.0478 5.54245 6.06034 3.2142 8.80945 2.67947V1.98716C8.80945 1.35002 9.34141 0.833313 9.99986 0.833313C10.6583 0.833313 11.1903 1.35002 11.1903 1.98716Z" fill="#227386"/>
+<ellipse cx="17.0833" cy="2.91665" rx="2.08333" ry="2.08333" fill="#D34E50"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/buy-coins-icon.svg b/assets/svg/oceanBreeze/buy-coins-icon.svg
new file mode 100644
index 000000000..d9613bccb
--- /dev/null
+++ b/assets/svg/oceanBreeze/buy-coins-icon.svg
@@ -0,0 +1,18 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_519_18707)">
+<g opacity="0.4">
+<path d="M22.2 6C23.3297 5.37187 24 4.59422 24 3.75C24 1.67906 19.9688 0 15 0C9.98906 0 6 1.67906 6 3.75C6 4.59422 6.67031 5.37187 7.8 6C7.80937 6.00469 7.81758 6.00937 7.82578 6.01406C7.83398 6.01875 7.84219 6.02344 7.85156 6.02813C8.23125 6.00938 8.61094 6 9 6C11.6344 6 14.0906 6.44062 15.9422 7.21406C16.1203 7.28906 16.2984 7.36875 16.4672 7.44844C18.8062 7.28906 20.8359 6.75469 22.2 6Z" fill="#227386"/>
+<path d="M19.9435 12.9151C19.7958 12.9551 19.6477 12.9951 19.5 13.0359V13.5C20.7602 13.5 21.9296 13.8885 22.8951 14.5522C23.5995 14.0172 24 13.4028 24 12.75V11.0906C23.4141 11.5734 22.7063 11.9672 21.9422 12.2859C21.3382 12.5376 20.6447 12.7253 19.9435 12.9151Z" fill="#227386"/>
+<path d="M18.3703 8.74688C19.0031 9.37969 19.5 10.2234 19.5 11.25V11.4984C20.4328 11.2734 21.2625 10.9781 21.9469 10.6359C21.9739 10.6209 22.0009 10.6021 22.0279 10.5833C22.0852 10.5432 22.1426 10.5032 22.2 10.5C23.3297 9.87187 24 9.09375 24 8.25V6.59063C23.4141 7.07344 22.7063 7.46719 21.9422 7.78594C20.9109 8.2125 19.6969 8.54063 18.3703 8.74688Z" fill="#227386"/>
+</g>
+<path d="M16.2 13.5C17.3297 12.8719 18 12.0938 18 11.25C18 9.17813 13.9688 7.5 9 7.5C4.02938 7.5 0 9.17813 0 11.25C0 12.0938 0.669375 12.8719 1.79953 13.5C1.85443 13.5031 1.91057 13.5415 1.96782 13.5807C1.9966 13.6004 2.02567 13.6203 2.055 13.6359C3.70594 14.4703 6.20625 15 9 15C11.9438 15 14.5594 14.4094 16.2 13.5Z" fill="#227386"/>
+<path d="M14.8788 15.6729C13.1948 16.2046 11.1571 16.5 9 16.5C6.36562 16.5 3.91125 16.0594 2.05922 15.2859C1.29469 14.9672 0.583594 14.5734 0 14.0906V15.75C0 16.5938 0.669375 17.3719 1.79953 18C3.44109 18.9094 6.05625 19.5 9 19.5C10.6471 19.5 12.1916 19.3159 13.5211 18.9937C13.6261 17.7367 14.1186 16.5898 14.8788 15.6729Z" fill="#227386"/>
+<path d="M13.5862 20.5191C13.7529 21.4936 14.1547 22.3879 14.731 23.1415C13.1742 23.6778 11.1771 24 9 24C4.02938 24 0 22.3219 0 20.25V18.5906C0.583594 19.0734 1.29469 19.4672 2.05922 19.7859C3.91125 20.5594 6.36562 21 9 21C10.6307 21 12.1932 20.8312 13.5862 20.5191Z" fill="#227386"/>
+<path d="M24 19.5C24 21.9844 21.9844 24 19.5 24C17.0156 24 15 21.9844 15 19.5C15 17.0156 17.0156 15 19.5 15C21.9844 15 24 17.0156 24 19.5ZM19 17.4719V18.9719H17.5C17.225 18.9719 17 19.225 17 19.4719C17 19.775 17.225 19.9719 17.5 19.9719H19V21.4719C19 21.775 19.225 21.9719 19.5 21.9719C19.775 21.9719 20 21.775 20 21.4719V19.9719H21.5C21.775 19.9719 22 19.775 22 19.4719C22 19.225 21.775 18.9719 21.5 18.9719H20V17.4719C20 17.225 19.775 16.9719 19.5 16.9719C19.225 16.9719 19 17.225 19 17.4719Z" fill="#227386"/>
+</g>
+<defs>
+<clipPath id="clip0_519_18707">
+<rect width="24" height="24" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/assets/svg/oceanBreeze/exchange-2.svg b/assets/svg/oceanBreeze/exchange-2.svg
new file mode 100644
index 000000000..7baeaf87f
--- /dev/null
+++ b/assets/svg/oceanBreeze/exchange-2.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M19.5 6.5L20.4343 7.33045C20.8552 6.85685 20.8552 6.14315 20.4343 5.66955L19.5 6.5ZM16.4343 1.16955C15.9756 0.653567 15.1855 0.607091 14.6695 1.06574C14.1536 1.52439 14.1071 2.31448 14.5657 2.83045L16.4343 1.16955ZM14.5657 10.1695C14.1071 10.6855 14.1536 11.4756 14.6695 11.9343C15.1855 12.3929 15.9756 12.3464 16.4343 11.8305L14.5657 10.1695ZM0.75 10.5C0.75 11.1904 1.30964 11.75 2 11.75C2.69036 11.75 3.25 11.1904 3.25 10.5H0.75ZM6 7.75H19.5V5.25H6V7.75ZM14.5657 2.83045L18.5657 7.33045L20.4343 5.66955L16.4343 1.16955L14.5657 2.83045ZM16.4343 11.8305L20.4343 7.33045L18.5657 5.66955L14.5657 10.1695L16.4343 11.8305ZM3.25 10.5C3.25 8.98122 4.48122 7.75 6 7.75V5.25C3.10051 5.25 0.75 7.60051 0.75 10.5H3.25Z" fill="#227386"/>
+<path opacity="0.4" d="M4.5 18L3.56574 17.1695C3.14475 17.6432 3.14475 18.3568 3.56574 18.8305L4.5 18ZM7.56574 23.3305C8.02439 23.8464 8.81448 23.8929 9.33045 23.4343C9.84643 22.9756 9.89291 22.1855 9.43426 21.6695L7.56574 23.3305ZM9.43426 14.3305C9.89291 13.8145 9.84643 13.0244 9.33046 12.5657C8.81448 12.1071 8.02439 12.1536 7.56574 12.6695L9.43426 14.3305ZM23.25 14C23.25 13.3096 22.6904 12.75 22 12.75C21.3096 12.75 20.75 13.3096 20.75 14L23.25 14ZM18 16.75L4.5 16.75L4.5 19.25L18 19.25L18 16.75ZM9.43426 21.6695L5.43426 17.1695L3.56574 18.8305L7.56574 23.3305L9.43426 21.6695ZM7.56574 12.6695L3.56574 17.1695L5.43426 18.8305L9.43426 14.3305L7.56574 12.6695ZM20.75 14C20.75 15.5188 19.5188 16.75 18 16.75L18 19.25C20.8995 19.25 23.25 16.8995 23.25 14L20.75 14Z" fill="#227386"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/stack-icon1.svg b/assets/svg/oceanBreeze/stack-icon1.svg
new file mode 100644
index 000000000..f316012d7
--- /dev/null
+++ b/assets/svg/oceanBreeze/stack-icon1.svg
@@ -0,0 +1,5 @@
+<svg width="70" height="70" viewBox="0 0 70 70" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M41.3715 9.57675C37.2965 7.22564 32.2041 10.1695 32.2041 14.8717C32.2041 19.5739 34.4762 23.6489 38.2004 26.163L53.9717 35.3057L54.0112 35.2908L69.9948 26.0543L41.3715 9.57675Z" fill="#B3B3B3"/>
+<path d="M38.2014 26.163C34.4771 23.6489 32.205 19.4159 32.205 14.8717C32.205 12.6342 33.3757 10.7671 35.0402 9.7101C34.9612 9.75455 35.1192 9.66564 35.0402 9.7101L10.0917 23.7279L6.08593 26.1481L3.35449 27.7188C5.07337 26.8446 7.22692 26.7754 9.14831 27.8917L16.0189 31.8037L22.0399 35.2859L38.0236 44.5076L53.9677 35.2958L38.1964 26.1531L38.2014 26.163Z" fill="#666666"/>
+<path d="M70 44.5187L38.0278 62.9917L31.992 59.5095L31.9673 59.4848L6.06054 44.5187C4.28733 43.3629 2.84505 41.7872 1.82755 40.014C0.642111 37.9691 0 35.618 0 33.1829C0 30.9899 1.10147 29.1771 2.70181 28.1004C2.91914 27.967 3.13153 27.8435 3.35874 27.725C5.07762 26.8507 7.23116 26.7816 9.15256 27.8979L15.9836 31.8394L22.0047 35.3068L22.0442 35.292L38.0278 44.5137L53.9719 35.3019L70 44.5137V44.5187Z" fill="#232323"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/tx-exchange-icon-failed.svg b/assets/svg/oceanBreeze/tx-exchange-icon-failed.svg
new file mode 100644
index 000000000..a54836bba
--- /dev/null
+++ b/assets/svg/oceanBreeze/tx-exchange-icon-failed.svg
@@ -0,0 +1,7 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path opacity="0.4" d="M23.0154 16.7681C23.6489 15.3066 24 13.6943 24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 18.6274 5.37258 24 12 24C13.6943 24 15.3066 23.6489 16.7681 23.0154C16.2832 22.2973 16 21.4317 16 20.5C16 18.0147 18.0147 16 20.5 16C21.4317 16 22.2973 16.2832 23.0154 16.7681Z" fill="#0056D2"/>
+<path d="M5.30071 12.4C4.91018 12.7905 4.91018 13.4236 5.30071 13.8142C5.69123 14.2047 6.32439 14.2047 6.71492 13.8142L5.30071 12.4ZM13.0789 6.03599L14.0787 6.05567C14.0839 5.78863 13.9821 5.53058 13.796 5.33904C13.6098 5.1475 13.3548 5.03839 13.0877 5.03603L13.0789 6.03599ZM9.00968 5.00004C8.45741 4.99516 8.00576 5.43891 8.00089 5.99117C7.99601 6.54344 8.43976 6.99509 8.99202 6.99996L9.00968 5.00004ZM12.001 9.98032C11.9902 10.5325 12.429 10.9889 12.9812 10.9998C13.5333 11.0107 13.9898 10.5719 14.0007 10.0197L12.001 9.98032ZM18.6429 11.6C19.0334 11.2095 19.0334 10.5764 18.6429 10.1858C18.2524 9.79531 17.6192 9.79531 17.2287 10.1858L18.6429 11.6ZM10.8647 17.964L9.8653 17.9297C9.85604 18.1992 9.95602 18.461 10.1426 18.6557C10.3291 18.8505 10.5864 18.9616 10.856 18.964L10.8647 17.964ZM14.9922 19C15.5444 19.0048 15.996 18.561 16.0008 18.0087C16.0056 17.4564 15.5618 17.0048 15.0096 17L14.9922 19ZM12.0003 14.0343C12.0192 13.4824 11.5871 13.0195 11.0352 13.0006C10.4832 12.9816 10.0204 13.4137 10.0014 13.9657L12.0003 14.0343ZM6.71492 13.8142L13.786 6.7431L12.3718 5.32889L5.30071 12.4L6.71492 13.8142ZM8.99202 6.99996L13.0701 7.03595L13.0877 5.03603L9.00968 5.00004L8.99202 6.99996ZM12.0791 6.01631L12.001 9.98032L14.0007 10.0197L14.0787 6.05567L12.0791 6.01631ZM17.2287 10.1858L10.1576 17.2569L11.5718 18.6711L18.6429 11.6L17.2287 10.1858ZM15.0096 17L10.8734 16.964L10.856 18.964L14.9922 19L15.0096 17ZM11.8641 17.9983L12.0003 14.0343L10.0014 13.9657L9.8653 17.9297L11.8641 17.9983Z" fill="#0056D2"/>
+<circle cx="20.5" cy="20.5" r="3.5" fill="#C00205"/>
+<path d="M19.4395 19.4395L20.5001 20.5001L21.5608 21.5608" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M19.5 21.5605L20.5607 20.4999L21.6213 19.4392" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/tx-exchange-icon-pending.svg b/assets/svg/oceanBreeze/tx-exchange-icon-pending.svg
new file mode 100644
index 000000000..5f9aa4256
--- /dev/null
+++ b/assets/svg/oceanBreeze/tx-exchange-icon-pending.svg
@@ -0,0 +1,6 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path opacity="0.4" d="M23.0154 16.7681C23.6489 15.3066 24 13.6943 24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 18.6274 5.37258 24 12 24C13.6943 24 15.3066 23.6489 16.7681 23.0154C16.2832 22.2973 16 21.4317 16 20.5C16 18.0147 18.0147 16 20.5 16C21.4317 16 22.2973 16.2832 23.0154 16.7681Z" fill="#0056D2"/>
+<circle cx="20.5" cy="20.5" r="3.5" fill="#F4C517"/>
+<path d="M20.5 19V20.5H21.5" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M5.30071 12.4C4.91018 12.7905 4.91018 13.4236 5.30071 13.8142C5.69123 14.2047 6.32439 14.2047 6.71492 13.8142L5.30071 12.4ZM13.0789 6.03599L14.0787 6.05567C14.0839 5.78863 13.9821 5.53058 13.796 5.33904C13.6098 5.1475 13.3548 5.03839 13.0877 5.03603L13.0789 6.03599ZM9.00968 5.00004C8.45741 4.99516 8.00576 5.43891 8.00089 5.99117C7.99601 6.54344 8.43976 6.99509 8.99202 6.99996L9.00968 5.00004ZM12.001 9.98032C11.9902 10.5325 12.429 10.9889 12.9812 10.9998C13.5333 11.0107 13.9898 10.5719 14.0007 10.0197L12.001 9.98032ZM18.6429 11.6C19.0334 11.2095 19.0334 10.5764 18.6429 10.1858C18.2524 9.79531 17.6192 9.79531 17.2287 10.1858L18.6429 11.6ZM10.8647 17.964L9.8653 17.9297C9.85605 18.1992 9.95602 18.461 10.1426 18.6557C10.3291 18.8505 10.5864 18.9616 10.856 18.964L10.8647 17.964ZM14.9922 19C15.5444 19.0048 15.996 18.561 16.0008 18.0087C16.0056 17.4564 15.5618 17.0048 15.0096 17L14.9922 19ZM12.0003 14.0343C12.0192 13.4824 11.5871 13.0195 11.0352 13.0006C10.4832 12.9816 10.0204 13.4137 10.0014 13.9657L12.0003 14.0343ZM6.71492 13.8142L13.786 6.7431L12.3718 5.32889L5.30071 12.4L6.71492 13.8142ZM8.99202 6.99996L13.0701 7.03595L13.0877 5.03603L9.00968 5.00004L8.99202 6.99996ZM12.0791 6.01631L12.001 9.98032L14.0007 10.0197L14.0787 6.05567L12.0791 6.01631ZM17.2287 10.1858L10.1576 17.2569L11.5718 18.6711L18.6429 11.6L17.2287 10.1858ZM15.0096 17L10.8734 16.964L10.856 18.964L14.9922 19L15.0096 17ZM11.8641 17.9983L12.0003 14.0343L10.0014 13.9657L9.8653 17.9297L11.8641 17.9983Z" fill="#0056D2"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/tx-exchange-icon.svg b/assets/svg/oceanBreeze/tx-exchange-icon.svg
new file mode 100644
index 000000000..fcd3ef9dc
--- /dev/null
+++ b/assets/svg/oceanBreeze/tx-exchange-icon.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle opacity="0.4" cx="12" cy="12" r="12" fill="#0056D2"/>
+<path d="M5.30071 12.4C4.91018 12.7905 4.91018 13.4236 5.30071 13.8142C5.69123 14.2047 6.32439 14.2047 6.71492 13.8142L5.30071 12.4ZM13.0789 6.03599L14.0787 6.05567C14.0839 5.78863 13.9821 5.53058 13.796 5.33904C13.6098 5.1475 13.3548 5.03839 13.0877 5.03603L13.0789 6.03599ZM9.00968 5.00004C8.45741 4.99516 8.00576 5.43891 8.00089 5.99117C7.99601 6.54344 8.43976 6.99509 8.99202 6.99996L9.00968 5.00004ZM12.001 9.98032C11.9902 10.5325 12.429 10.9889 12.9812 10.9998C13.5333 11.0107 13.9898 10.5719 14.0007 10.0197L12.001 9.98032ZM18.6429 11.6C19.0334 11.2095 19.0334 10.5764 18.6429 10.1858C18.2524 9.79531 17.6192 9.79531 17.2287 10.1858L18.6429 11.6ZM10.8647 17.964L9.8653 17.9297C9.85604 18.1992 9.95602 18.461 10.1426 18.6557C10.3291 18.8505 10.5864 18.9616 10.856 18.964L10.8647 17.964ZM14.9922 19C15.5444 19.0048 15.996 18.561 16.0008 18.0087C16.0056 17.4564 15.5618 17.0048 15.0096 17L14.9922 19ZM12.0003 14.0343C12.0192 13.4824 11.5871 13.0195 11.0352 13.0006C10.4832 12.9816 10.0204 13.4137 10.0014 13.9657L12.0003 14.0343ZM6.71492 13.8142L13.786 6.7431L12.3718 5.32889L5.30071 12.4L6.71492 13.8142ZM8.99202 6.99996L13.0701 7.03595L13.0877 5.03603L9.00968 5.00004L8.99202 6.99996ZM12.0791 6.01631L12.001 9.98032L14.0007 10.0197L14.0787 6.05567L12.0791 6.01631ZM17.2287 10.1858L10.1576 17.2569L11.5718 18.6711L18.6429 11.6L17.2287 10.1858ZM15.0096 17L10.8734 16.964L10.856 18.964L14.9922 19L15.0096 17ZM11.8641 17.9983L12.0003 14.0343L10.0014 13.9657L9.8653 17.9297L11.8641 17.9983Z" fill="#0056D2"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/tx-icon-receive-failed.svg b/assets/svg/oceanBreeze/tx-icon-receive-failed.svg
new file mode 100644
index 000000000..189bd15c9
--- /dev/null
+++ b/assets/svg/oceanBreeze/tx-icon-receive-failed.svg
@@ -0,0 +1,7 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M23.0154 16.7681C23.6489 15.3066 24 13.6943 24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 18.6274 5.37258 24 12 24C13.6943 24 15.3066 23.6489 16.7681 23.0154C16.2832 22.2973 16 21.4317 16 20.5C16 18.0147 18.0147 16 20.5 16C21.4317 16 22.2973 16.2832 23.0154 16.7681Z" fill="#00A578"/>
+<circle cx="20.5" cy="20.5" r="3.5" fill="#C00205"/>
+<path d="M16 8L8 16M8 16H14M8 16V10" stroke="#00A578" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M19.4395 19.4395L20.5001 20.5001L21.5608 21.5608" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M19.5 21.5605L20.5607 20.4999L21.6213 19.4392" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/tx-icon-receive-pending.svg b/assets/svg/oceanBreeze/tx-icon-receive-pending.svg
new file mode 100644
index 000000000..64ea8da3d
--- /dev/null
+++ b/assets/svg/oceanBreeze/tx-icon-receive-pending.svg
@@ -0,0 +1,5 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path opacity="0.4" d="M23.0154 16.7681C23.6489 15.3066 24 13.6943 24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 18.6274 5.37258 24 12 24C13.6943 24 15.3066 23.6489 16.7681 23.0154C16.2832 22.2973 16 21.4317 16 20.5C16 18.0147 18.0147 16 20.5 16C21.4317 16 22.2973 16.2832 23.0154 16.7681Z" fill="#00A578"/>
+<path d="M16 8L8 16M8 16H14M8 16V10" stroke="#00A578" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M20.5 24C22.433 24 24 22.433 24 20.5C24 18.567 22.433 17 20.5 17C18.567 17 17 18.567 17 20.5C17 22.433 18.567 24 20.5 24ZM21 19C21 18.7239 20.7761 18.5 20.5 18.5C20.2239 18.5 20 18.7239 20 19V20.5C20 20.7761 20.2239 21 20.5 21H21.5C21.7761 21 22 20.7761 22 20.5C22 20.2239 21.7761 20 21.5 20H21V19Z" fill="#F4C517"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/tx-icon-receive.svg b/assets/svg/oceanBreeze/tx-icon-receive.svg
new file mode 100644
index 000000000..1076d8d57
--- /dev/null
+++ b/assets/svg/oceanBreeze/tx-icon-receive.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle opacity="0.4" cx="12" cy="12" r="12" fill="#00A578"/>
+<path d="M16 8L8 16M8 16H14M8 16V10" stroke="#00A578" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/tx-icon-send-failed.svg b/assets/svg/oceanBreeze/tx-icon-send-failed.svg
new file mode 100644
index 000000000..9751b61e8
--- /dev/null
+++ b/assets/svg/oceanBreeze/tx-icon-send-failed.svg
@@ -0,0 +1,7 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path opacity="0.4" d="M23.0154 16.7681C23.6489 15.3066 24 13.6943 24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 18.6274 5.37258 24 12 24C13.6943 24 15.3066 23.6489 16.7681 23.0154C16.2832 22.2973 16 21.4317 16 20.5C16 18.0147 18.0147 16 20.5 16C21.4317 16 22.2973 16.2832 23.0154 16.7681Z" fill="#FE805C"/>
+<path d="M8 16L16 8M16 8L10 8M16 8L16 14" stroke="#FE805C" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
+<circle cx="20.5" cy="20.5" r="3.5" fill="#C00205"/>
+<path d="M19.4395 19.4395L20.5001 20.5001L21.5608 21.5608" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M19.5 21.5605L20.5607 20.4999L21.6213 19.4392" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/tx-icon-send-pending.svg b/assets/svg/oceanBreeze/tx-icon-send-pending.svg
new file mode 100644
index 000000000..e4ec777e3
--- /dev/null
+++ b/assets/svg/oceanBreeze/tx-icon-send-pending.svg
@@ -0,0 +1,6 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path opacity="0.4" d="M23.0154 16.7681C23.6489 15.3066 24 13.6943 24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 18.6274 5.37258 24 12 24C13.6943 24 15.3066 23.6489 16.7681 23.0154C16.2832 22.2973 16 21.4317 16 20.5C16 18.0147 18.0147 16 20.5 16C21.4317 16 22.2973 16.2832 23.0154 16.7681Z" fill="#FE805C"/>
+<path d="M8 16L16 8M16 8L10 8M16 8L16 14" stroke="#FE805C" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
+<circle cx="20.5" cy="20.5" r="3.5" fill="#F4C517"/>
+<path d="M20.5 19V20.5H21.5" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/assets/svg/oceanBreeze/tx-icon-send.svg b/assets/svg/oceanBreeze/tx-icon-send.svg
new file mode 100644
index 000000000..ee32aa6b4
--- /dev/null
+++ b/assets/svg/oceanBreeze/tx-icon-send.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<circle opacity="0.4" cx="12" cy="12" r="12" fill="#FE805C"/>
+<path d="M8 16L16 8M16 8L10 8M16 8L16 14" stroke="#FE805C" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart
index d7d2ebc6f..c423ec491 100644
--- a/lib/utilities/assets.dart
+++ b/lib/utilities/assets.dart
@@ -60,12 +60,13 @@ class _SVG {
       "assets/svg/${Theme.of(context).extension<StackColors>()!.themeType.name}/tx-exchange-icon-failed.svg";
 
   String get themeOcean => "assets/svg/ocean-breeze-theme.svg";
+  String get themeLight => "assets/svg/light-mode.svg";
+  String get themeDark => "assets/svg/dark-theme.svg";
+
   String get circleSliders => "assets/svg/configuration.svg";
   String get circlePlus => "assets/svg/plus-circle.svg";
   String get framedGear => "assets/svg/framed-gear.svg";
   String get framedAddressBook => "assets/svg/framed-address-book.svg";
-  String get themeLight => "assets/svg/light/light-mode.svg";
-  String get themeDark => "assets/svg/dark/dark-theme.svg";
   String get circleNode => "assets/svg/node-circle.svg";
   String get circleSun => "assets/svg/sun-circle.svg";
   String get circleArrowRotate => "assets/svg/rotate-circle.svg";
diff --git a/pubspec.yaml b/pubspec.yaml
index 94670af1a..6a721c5c1 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -205,9 +205,6 @@ flutter:
     - assets/svg/plus.svg
     - assets/svg/gear.svg
     - assets/svg/bell.svg
-    - assets/svg/light/bell-new.svg
-    - assets/svg/dark/bell-new.svg
-    - assets/svg/stack-icon1.svg
     - assets/svg/arrow-left-fa.svg
     - assets/svg/copy-fa.svg
     - assets/svg/star.svg
@@ -220,10 +217,7 @@ flutter:
     - assets/svg/bars.svg
     - assets/svg/filter.svg
     - assets/svg/pending.svg
-    - assets/svg/dark/exchange-2.svg
-    - assets/svg/light/exchange-2.svg
     - assets/svg/signal-stream.svg
-    - assets/svg/buy-coins-icon.svg
     - assets/svg/Ellipse-43.svg
     - assets/svg/Ellipse-42.svg
     - assets/svg/arrow-rotate.svg
@@ -265,25 +259,7 @@ flutter:
     - assets/svg/ellipsis-vertical1.svg
     - assets/svg/dice-alt.svg
     - assets/svg/circle-arrow-up-right2.svg
-    - assets/svg/dark/tx-exchange-icon.svg
-    - assets/svg/light/tx-exchange-icon.svg
-    - assets/svg/dark/tx-exchange-icon-pending.svg
-    - assets/svg/light/tx-exchange-icon-pending.svg
-    - assets/svg/dark/tx-exchange-icon-failed.svg
-    - assets/svg/light/tx-exchange-icon-failed.svg
     - assets/svg/loader.svg
-    - assets/svg/dark/tx-icon-send.svg
-    - assets/svg/light/tx-icon-send.svg
-    - assets/svg/dark/tx-icon-send-pending.svg
-    - assets/svg/light/tx-icon-send-pending.svg
-    - assets/svg/dark/tx-icon-send-failed.svg
-    - assets/svg/light/tx-icon-send-failed.svg
-    - assets/svg/dark/tx-icon-receive.svg
-    - assets/svg/light/tx-icon-receive.svg
-    - assets/svg/dark/tx-icon-receive-pending.svg
-    - assets/svg/light/tx-icon-receive-pending.svg
-    - assets/svg/dark/tx-icon-receive-failed.svg
-    - assets/svg/light/tx-icon-receive-failed.svg
     - assets/svg/add-backup.svg
     - assets/svg/auto-backup.svg
     - assets/svg/restore-backup.svg
@@ -305,8 +281,6 @@ flutter:
     - assets/svg/rotate-circle.svg
     - assets/svg/sun-circle.svg
     - assets/svg/node-circle.svg
-    - assets/svg/dark/dark-theme.svg
-    - assets/svg/light/light-mode.svg
     - assets/svg/address-book-desktop.svg
     - assets/svg/about-desktop.svg
     - assets/svg/exchange-desktop.svg
@@ -316,7 +290,6 @@ flutter:
     - assets/svg/arrow-down.svg
     - assets/svg/plus-circle.svg
     - assets/svg/configuration.svg
-    - assets/svg/ocean-breeze-theme.svg
     # coin icons
     - assets/svg/coin_icons/Bitcoin.svg
     - assets/svg/coin_icons/Litecoin.svg
@@ -348,6 +321,56 @@ flutter:
     - assets/svg/exchange_icons/change_now_logo_1.svg
     - assets/svg/exchange_icons/simpleswap-icon.svg
 
+    # theme selectors
+    - assets/svg/dark-theme.svg
+    - assets/svg/light-mode.svg
+    - assets/svg/ocean-breeze-theme.svg
+
+    # light theme specific
+    - assets/svg/light/tx-exchange-icon.svg
+    - assets/svg/light/tx-exchange-icon-pending.svg
+    - assets/svg/light/tx-exchange-icon-failed.svg
+    - assets/svg/light/tx-icon-send.svg
+    - assets/svg/light/tx-icon-send-pending.svg
+    - assets/svg/light/tx-icon-send-failed.svg
+    - assets/svg/light/tx-icon-receive.svg
+    - assets/svg/light/tx-icon-receive-pending.svg
+    - assets/svg/light/tx-icon-receive-failed.svg
+    - assets/svg/light/exchange-2.svg
+    - assets/svg/light/bell-new.svg
+    - assets/svg/light/stack-icon1.svg
+    - assets/svg/light/buy-coins-icon.svg
+
+    # dark theme specific
+    - assets/svg/dark/tx-exchange-icon.svg
+    - assets/svg/dark/tx-exchange-icon-pending.svg
+    - assets/svg/dark/tx-exchange-icon-failed.svg
+    - assets/svg/dark/tx-icon-send.svg
+    - assets/svg/dark/tx-icon-send-pending.svg
+    - assets/svg/dark/tx-icon-send-failed.svg
+    - assets/svg/dark/tx-icon-receive.svg
+    - assets/svg/dark/tx-icon-receive-pending.svg
+    - assets/svg/dark/tx-icon-receive-failed.svg
+    - assets/svg/dark/exchange-2.svg
+    - assets/svg/dark/bell-new.svg
+    - assets/svg/dark/stack-icon1.svg
+    - assets/svg/dark/buy-coins-icon.svg
+
+    # light theme specific
+    - assets/svg/oceanBreeze/tx-exchange-icon.svg
+    - assets/svg/oceanBreeze/tx-exchange-icon-pending.svg
+    - assets/svg/oceanBreeze/tx-exchange-icon-failed.svg
+    - assets/svg/oceanBreeze/tx-icon-send.svg
+    - assets/svg/oceanBreeze/tx-icon-send-pending.svg
+    - assets/svg/oceanBreeze/tx-icon-send-failed.svg
+    - assets/svg/oceanBreeze/tx-icon-receive.svg
+    - assets/svg/oceanBreeze/tx-icon-receive-pending.svg
+    - assets/svg/oceanBreeze/tx-icon-receive-failed.svg
+    - assets/svg/oceanBreeze/exchange-2.svg
+    - assets/svg/oceanBreeze/bell-new.svg
+    - assets/svg/oceanBreeze/stack-icon1.svg
+    - assets/svg/oceanBreeze/buy-coins-icon.svg
+
   # An image asset can refer to one or more resolution-specific "variants", see
   # https://flutter.dev/assets-and-images/#resolution-aware.
   # For details regarding adding assets from package dependencies, see

From 792b91b7c4d27c7212b251150ad4fafef39b96a8 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Fri, 18 Nov 2022 11:26:27 -0700
Subject: [PATCH 039/100] syncing pref options show on button press + shows
 card w current syncing prefs

---
 .../syncing_preferences_settings.dart         | 116 ++++++++++++++----
 1 file changed, 91 insertions(+), 25 deletions(-)

diff --git a/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart b/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart
index 815e506db..720d77b8b 100644
--- a/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart
@@ -3,9 +3,13 @@ import 'package:flutter/src/widgets/framework.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/svg.dart';
 import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart';
+import 'package:stackwallet/providers/global/prefs_provider.dart';
 import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/rounded_container.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 
 class SyncingPreferencesSettings extends ConsumerStatefulWidget {
@@ -20,6 +24,19 @@ class SyncingPreferencesSettings extends ConsumerStatefulWidget {
 
 class _SyncingPreferencesSettings
     extends ConsumerState<SyncingPreferencesSettings> {
+  String _currentTypeDescription(SyncingType type) {
+    switch (type) {
+      case SyncingType.currentWalletOnly:
+        return "Sync only currently open wallet";
+      case SyncingType.selectedWalletsAtStartup:
+        return "Sync only selected wallets at startup";
+      case SyncingType.allWalletsOnStartup:
+        return "Sync all wallets at startup";
+    }
+  }
+
+  late bool changePrefs = false;
+
   @override
   Widget build(BuildContext context) {
     debugPrint("BUILD: $runtimeType");
@@ -34,13 +51,40 @@ class _SyncingPreferencesSettings
             child: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
               children: [
-                Padding(
-                  padding: const EdgeInsets.all(8.0),
-                  child: SvgPicture.asset(
-                    Assets.svg.circleArrowRotate,
-                    width: 48,
-                    height: 48,
-                  ),
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  children: [
+                    Padding(
+                      padding: const EdgeInsets.all(8.0),
+                      child: SvgPicture.asset(
+                        Assets.svg.circleArrowRotate,
+                        width: 48,
+                        height: 48,
+                      ),
+                    ),
+                    Padding(
+                      padding: const EdgeInsets.all(8.0),
+                      child: RoundedContainer(
+                        color: Theme.of(context)
+                            .extension<StackColors>()!
+                            .buttonBackSecondaryDisabled,
+                        child: Padding(
+                          padding: const EdgeInsets.all(8.0),
+                          child: Text(
+                            _currentTypeDescription(ref.watch(
+                                prefsChangeNotifierProvider
+                                    .select((value) => value.syncType))),
+                            style: STextStyles.desktopTextExtraSmall(context)
+                                .copyWith(
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textDark2),
+                            textAlign: TextAlign.left,
+                          ),
+                        ),
+                      ),
+                    ),
+                  ],
                 ),
                 Column(
                   crossAxisAlignment: CrossAxisAlignment.stretch,
@@ -67,28 +111,50 @@ class _SyncingPreferencesSettings
                     ),
                   ],
                 ),
-
-                ///TODO: ONLY SHOW SYNC OPTIONS ON BUTTON PRESS
-                Column(
-                  children: const [
-                    SyncingOptionsView(),
-                  ],
-                ),
                 Column(
                   crossAxisAlignment: CrossAxisAlignment.start,
                   children: [
                     Padding(
-                      padding: const EdgeInsets.all(
-                        10,
-                      ),
-                      child: PrimaryButton(
-                        width: 210,
-                        buttonHeight: ButtonHeight.m,
-                        enabled: true,
-                        label: "Change preferences",
-                        onPressed: () {},
-                      ),
-                    ),
+                        padding: const EdgeInsets.all(
+                          10,
+                        ),
+                        child: changePrefs
+                            ? SizedBox(
+                                width: 512,
+                                child: Column(
+                                  crossAxisAlignment: CrossAxisAlignment.start,
+                                  children: [
+                                    const SyncingOptionsView(),
+                                    PrimaryButton(
+                                      width: 200,
+                                      buttonHeight: ButtonHeight.m,
+                                      enabled: true,
+                                      label: "Save",
+                                      onPressed: () {
+                                        setState(() {
+                                          changePrefs = false;
+                                        });
+                                      },
+                                    ),
+                                  ],
+                                ),
+                              )
+                            : Column(
+                                children: [
+                                  const SizedBox(height: 10),
+                                  PrimaryButton(
+                                    width: 200,
+                                    buttonHeight: ButtonHeight.m,
+                                    enabled: true,
+                                    label: "Change preferences",
+                                    onPressed: () {
+                                      setState(() {
+                                        changePrefs = true;
+                                      });
+                                    },
+                                  ),
+                                ],
+                              )),
                   ],
                 ),
               ],

From 7ef31cbf87a80598478c2ef68a4ff98cbe3c130a Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 12:34:25 -0600
Subject: [PATCH 040/100] add back exchange menu option and adjust icon color

---
 .../home/desktop_menu.dart                    | 76 ++++++++++---------
 lib/utilities/theme/ocean_breeze_colors.dart  |  2 +-
 2 files changed, 41 insertions(+), 37 deletions(-)

diff --git a/lib/pages_desktop_specific/home/desktop_menu.dart b/lib/pages_desktop_specific/home/desktop_menu.dart
index bdaa1d6ce..60a424a06 100644
--- a/lib/pages_desktop_specific/home/desktop_menu.dart
+++ b/lib/pages_desktop_specific/home/desktop_menu.dart
@@ -104,10 +104,10 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
                                     .state
                             ? Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                             : Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                                 .withOpacity(0.8),
                       ),
                       label: "My Stack",
@@ -120,29 +120,33 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
                     const SizedBox(
                       height: 2,
                     ),
-                    // DesktopMenuItem(
-                    //   icon: SvgPicture.asset(
-                    //     Assets.svg.exchangeDesktop,
-                    //     width: 20,
-                    //     height: 20,
-                    //     color: DesktopMenuItemId.exchange == ref.watch(currentDesktopMenuItemProvider.state).state
-                    //         ? Theme.of(context)
-                    //             .extension<StackColors>()!
-                    //             .textDark
-                    //         : Theme.of(context)
-                    //             .extension<StackColors>()!
-                    //             .textDark
-                    //             .withOpacity(0.8),
-                    //   ),
-                    //   label: "Exchange",
-                    //   value: DesktopMenuItemId.exchange,
-                    //   group: ref.watch(currentDesktopMenuItemProvider.state).state,
-                    //   onChanged: updateSelectedMenuItem,
-                    //   iconOnly: _width == minimizedWidth,
-                    // ),
-                    // const SizedBox(
-                    //   height: 2,
-                    // ),
+                    DesktopMenuItem(
+                      icon: SvgPicture.asset(
+                        Assets.svg.exchangeDesktop,
+                        width: 20,
+                        height: 20,
+                        color: DesktopMenuItemId.exchange ==
+                                ref
+                                    .watch(currentDesktopMenuItemProvider.state)
+                                    .state
+                            ? Theme.of(context)
+                                .extension<StackColors>()!
+                                .accentColorDark
+                            : Theme.of(context)
+                                .extension<StackColors>()!
+                                .accentColorDark
+                                .withOpacity(0.8),
+                      ),
+                      label: "Exchange",
+                      value: DesktopMenuItemId.exchange,
+                      group:
+                          ref.watch(currentDesktopMenuItemProvider.state).state,
+                      onChanged: updateSelectedMenuItem,
+                      iconOnly: _width == minimizedWidth,
+                    ),
+                    const SizedBox(
+                      height: 2,
+                    ),
                     DesktopMenuItem(
                       icon: SvgPicture.asset(
                         Assets.svg.bell,
@@ -154,10 +158,10 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
                                     .state
                             ? Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                             : Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                                 .withOpacity(0.8),
                       ),
                       label: "Notifications",
@@ -181,10 +185,10 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
                                     .state
                             ? Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                             : Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                                 .withOpacity(0.8),
                       ),
                       label: "Address Book",
@@ -208,10 +212,10 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
                                     .state
                             ? Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                             : Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                                 .withOpacity(0.8),
                       ),
                       label: "Settings",
@@ -235,10 +239,10 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
                                     .state
                             ? Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                             : Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                                 .withOpacity(0.8),
                       ),
                       label: "Support",
@@ -262,10 +266,10 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
                                     .state
                             ? Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                             : Theme.of(context)
                                 .extension<StackColors>()!
-                                .textDark
+                                .accentColorDark
                                 .withOpacity(0.8),
                       ),
                       label: "About",
@@ -283,7 +287,7 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
                         height: 20,
                         color: Theme.of(context)
                             .extension<StackColors>()!
-                            .textDark
+                            .accentColorDark
                             .withOpacity(0.8),
                       ),
                       label: "Exit",
diff --git a/lib/utilities/theme/ocean_breeze_colors.dart b/lib/utilities/theme/ocean_breeze_colors.dart
index ff2f4e85e..1eb06e068 100644
--- a/lib/utilities/theme/ocean_breeze_colors.dart
+++ b/lib/utilities/theme/ocean_breeze_colors.dart
@@ -21,7 +21,7 @@ class OceanBreezeColors extends StackColorTheme {
   @override
   Color get accentColorOrange => const Color(0xFFFF985F);
   @override
-  Color get accentColorDark => const Color(0xFF232323);
+  Color get accentColorDark => const Color(0xFF227386);
 
   @override
   Color get shadow => const Color(0xFF388192);

From ea143d9ffa901d30cf9f2631b0362fab80cfee71 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 12:45:42 -0600
Subject: [PATCH 041/100] basic desktop exchange layout

---
 .../desktop_exchange_view.dart                |  89 +++++++++++++++
 .../subwidgets/desktop_trade_history.dart     | 103 ++++++++++++++++++
 .../home/desktop_home_view.dart               |  10 +-
 lib/route_generator.dart                      |   7 ++
 4 files changed, 205 insertions(+), 4 deletions(-)
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart

diff --git a/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart b/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart
new file mode 100644
index 000000000..0f44eb59b
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart
@@ -0,0 +1,89 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
+import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+
+class DesktopExchangeView extends StatefulWidget {
+  const DesktopExchangeView({Key? key}) : super(key: key);
+
+  static const String routeName = "/desktopExchange";
+
+  @override
+  State<DesktopExchangeView> createState() => _DesktopExchangeViewState();
+}
+
+class _DesktopExchangeViewState extends State<DesktopExchangeView> {
+  @override
+  Widget build(BuildContext context) {
+    return DesktopScaffold(
+      appBar: DesktopAppBar(
+        isCompactHeight: true,
+        leading: Padding(
+          padding: const EdgeInsets.only(
+            left: 24,
+          ),
+          child: Text(
+            "Exchange",
+            style: STextStyles.desktopH3(context),
+          ),
+        ),
+      ),
+      body: Padding(
+        padding: const EdgeInsets.only(
+          left: 24,
+          right: 24,
+          bottom: 24,
+        ),
+        child: Row(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            Expanded(
+              child: Column(
+                mainAxisSize: MainAxisSize.min,
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Text(
+                    "Exchange details",
+                    style: STextStyles.desktopTextExtraExtraSmall(context),
+                  ),
+                  const SizedBox(
+                    height: 16,
+                  ),
+                  const RoundedWhiteContainer(
+                    padding: EdgeInsets.all(24),
+                    child: ExchangeForm(),
+                  ),
+                ],
+              ),
+            ),
+            const SizedBox(
+              width: 16,
+            ),
+            Expanded(
+              child: Column(
+                mainAxisSize: MainAxisSize.min,
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Text(
+                    "Exchange details",
+                    style: STextStyles.desktopTextExtraExtraSmall(context),
+                  ),
+                  const SizedBox(
+                    height: 16,
+                  ),
+                  const RoundedWhiteContainer(
+                    padding: EdgeInsets.all(0),
+                    child: DesktopTradeHistory(),
+                  ),
+                ],
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
new file mode 100644
index 000000000..40eeb8c1b
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
@@ -0,0 +1,103 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:stackwallet/pages/exchange_view/trade_details_view.dart';
+import 'package:stackwallet/providers/exchange/trade_sent_from_stack_lookup_provider.dart';
+import 'package:stackwallet/providers/global/trades_service_provider.dart';
+import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+import 'package:stackwallet/widgets/trade_card.dart';
+import 'package:tuple/tuple.dart';
+
+class DesktopTradeHistory extends ConsumerStatefulWidget {
+  const DesktopTradeHistory({Key? key}) : super(key: key);
+
+  @override
+  ConsumerState<DesktopTradeHistory> createState() =>
+      _DesktopTradeHistoryState();
+}
+
+class _DesktopTradeHistoryState extends ConsumerState<DesktopTradeHistory> {
+  @override
+  Widget build(BuildContext context) {
+    final trades =
+        ref.watch(tradesServiceProvider.select((value) => value.trades));
+
+    final tradeCount = trades.length;
+    final hasHistory = tradeCount > 0;
+
+    if (hasHistory) {
+      return ListView.separated(
+        itemBuilder: (context, index) {
+          return TradeCard(
+            key: Key("tradeCard_${trades[index].uuid}"),
+            trade: trades[index],
+            onTap: () async {
+              final String tradeId = trades[index].tradeId;
+
+              final lookup = ref.read(tradeSentFromStackLookupProvider).all;
+
+              debugPrint("ALL: $lookup");
+
+              final String? txid = ref
+                  .read(tradeSentFromStackLookupProvider)
+                  .getTxidForTradeId(tradeId);
+              final List<String>? walletIds = ref
+                  .read(tradeSentFromStackLookupProvider)
+                  .getWalletIdsForTradeId(tradeId);
+
+              if (txid != null && walletIds != null && walletIds.isNotEmpty) {
+                final manager = ref
+                    .read(walletsChangeNotifierProvider)
+                    .getManager(walletIds.first);
+
+                debugPrint("name: ${manager.walletName}");
+
+                // TODO store tx data completely locally in isar so we don't lock up ui here when querying txData
+                final txData = await manager.transactionData;
+
+                final tx = txData.getAllTransactions()[txid];
+
+                if (mounted) {
+                  unawaited(
+                    Navigator.of(context).pushNamed(
+                      TradeDetailsView.routeName,
+                      arguments: Tuple4(
+                          tradeId, tx, walletIds.first, manager.walletName),
+                    ),
+                  );
+                }
+              } else {
+                unawaited(
+                  Navigator.of(context).pushNamed(
+                    TradeDetailsView.routeName,
+                    arguments: Tuple4(tradeId, null, walletIds?.first, null),
+                  ),
+                );
+              }
+            },
+          );
+        },
+        separatorBuilder: (context, index) {
+          return Container(
+            height: 1,
+            color: Theme.of(context).extension<StackColors>()!.background,
+          );
+        },
+        itemCount: tradeCount,
+      );
+    } else {
+      return RoundedWhiteContainer(
+        child: Center(
+          child: Text(
+            "Trades will appear here",
+            style: STextStyles.desktopTextExtraExtraSmall(context),
+          ),
+        ),
+      );
+    }
+  }
+}
diff --git a/lib/pages_desktop_specific/home/desktop_home_view.dart b/lib/pages_desktop_specific/home/desktop_home_view.dart
index b1c35f00b..9791cd867 100644
--- a/lib/pages_desktop_specific/home/desktop_home_view.dart
+++ b/lib/pages_desktop_specific/home/desktop_home_view.dart
@@ -1,5 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/address_book_view/desktop_address_book.dart';
 import 'package:stackwallet/pages_desktop_specific/home/desktop_menu.dart';
 import 'package:stackwallet/pages_desktop_specific/home/desktop_settings_view.dart';
@@ -29,10 +30,11 @@ class _DesktopHomeViewState extends ConsumerState<DesktopHomeView> {
       onGenerateRoute: RouteGenerator.generateRoute,
       initialRoute: MyStackView.routeName,
     ),
-    // Container(
-    //   // todo: exchange
-    //   color: Colors.green,
-    // ),
+    DesktopMenuItemId.exchange: const Navigator(
+      key: Key("desktopExchangeHomeKey"),
+      onGenerateRoute: RouteGenerator.generateRoute,
+      initialRoute: DesktopExchangeView.routeName,
+    ),
     DesktopMenuItemId.notifications: const Navigator(
       key: Key("desktopNotificationsHomeKey"),
       onGenerateRoute: RouteGenerator.generateRoute,
diff --git a/lib/route_generator.dart b/lib/route_generator.dart
index d7865d013..8ccc923bc 100644
--- a/lib/route_generator.dart
+++ b/lib/route_generator.dart
@@ -85,6 +85,7 @@ import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_sear
 import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
 import 'package:stackwallet/pages/wallets_view/wallets_view.dart';
 import 'package:stackwallet/pages_desktop_specific/create_password/create_password_view.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart';
 import 'package:stackwallet/pages_desktop_specific/forgot_password_desktop_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/address_book_view/desktop_address_book.dart';
 import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart';
@@ -1019,6 +1020,12 @@ class RouteGenerator {
             builder: (_) => const DesktopNotificationsView(),
             settings: RouteSettings(name: settings.name));
 
+      case DesktopExchangeView.routeName:
+        return getRoute(
+            shouldUseMaterialRoute: useMaterialPageRoute,
+            builder: (_) => const DesktopExchangeView(),
+            settings: RouteSettings(name: settings.name));
+
       case DesktopSettingsView.routeName:
         return getRoute(
             shouldUseMaterialRoute: useMaterialPageRoute,

From 83e2554b545e62a6cf4af323093a150dfe054812 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Fri, 18 Nov 2022 12:42:12 -0700
Subject: [PATCH 042/100] mobile theme radio buttons

---
 .../appearance_settings_view.dart             | 364 +++++++++++++++---
 1 file changed, 309 insertions(+), 55 deletions(-)

diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart
index 3a1b842f6..d1e893802 100644
--- a/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart
+++ b/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart
@@ -8,6 +8,7 @@ import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/color_theme.dart';
 import 'package:stackwallet/utilities/theme/dark_colors.dart';
 import 'package:stackwallet/utilities/theme/light_colors.dart';
+import 'package:stackwallet/utilities/theme/ocean_breeze_colors.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
@@ -18,6 +19,17 @@ class AppearanceSettingsView extends ConsumerWidget {
 
   static const String routeName = "/appearanceSettings";
 
+  String chooseThemeType(ThemeType type) {
+    switch (type) {
+      case ThemeType.light:
+        return "Light theme";
+      case ThemeType.oceanBreeze:
+        return "Ocean theme";
+      case ThemeType.dark:
+        return "Dark theme";
+    }
+  }
+
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     return Scaffold(
@@ -100,68 +112,39 @@ class AppearanceSettingsView extends ConsumerWidget {
                         height: 10,
                       ),
                       RoundedWhiteContainer(
-                        child: Consumer(
-                          builder: (_, ref, __) {
-                            return RawMaterialButton(
-                              splashColor: Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .highlight,
-                              materialTapTargetSize:
-                                  MaterialTapTargetSize.shrinkWrap,
-                              shape: RoundedRectangleBorder(
-                                borderRadius: BorderRadius.circular(
-                                  Constants.size.circularBorderRadius,
-                                ),
-                              ),
-                              onPressed: null,
-                              child: Padding(
-                                padding:
-                                    const EdgeInsets.symmetric(vertical: 8),
-                                child: Row(
-                                  mainAxisAlignment:
-                                      MainAxisAlignment.spaceBetween,
+                        padding: const EdgeInsets.all(0),
+                        child: RawMaterialButton(
+                          // splashColor: Theme.of(context).extension<StackColors>()!.highlight,
+                          padding: const EdgeInsets.all(0),
+                          materialTapTargetSize:
+                              MaterialTapTargetSize.shrinkWrap,
+                          shape: RoundedRectangleBorder(
+                            borderRadius: BorderRadius.circular(
+                              Constants.size.circularBorderRadius,
+                            ),
+                          ),
+                          onPressed: null,
+                          child: Padding(
+                            padding: const EdgeInsets.all(12),
+                            child: Row(
+                              children: [
+                                Column(
+                                  crossAxisAlignment: CrossAxisAlignment.start,
                                   children: [
                                     Text(
-                                      "Enable dark mode",
+                                      "Choose Theme",
                                       style: STextStyles.titleBold12(context),
                                       textAlign: TextAlign.left,
                                     ),
-                                    SizedBox(
-                                      height: 20,
-                                      width: 40,
-                                      child: DraggableSwitchButton(
-                                        isOn: (DB.instance.get<dynamic>(
-                                                    boxName: DB.boxNameTheme,
-                                                    key: "colorScheme")
-                                                as String?) ==
-                                            "dark",
-                                        onValueChanged: (newValue) {
-                                          DB.instance.put<dynamic>(
-                                            boxName: DB.boxNameTheme,
-                                            key: "colorScheme",
-                                            value: (newValue
-                                                    ? ThemeType.dark
-                                                    : (newValue
-                                                        ? ThemeType.light
-                                                        : ThemeType
-                                                            .oceanBreeze))
-                                                .name,
-                                          );
-                                          ref
-                                                  .read(colorThemeProvider.state)
-                                                  .state =
-                                              StackColors.fromStackColorTheme(
-                                                  newValue
-                                                      ? DarkColors()
-                                                      : LightColors());
-                                        },
-                                      ),
-                                    )
+                                    const Padding(
+                                      padding: EdgeInsets.all(10),
+                                      child: ThemeOptionsView(),
+                                    ),
                                   ],
                                 ),
-                              ),
-                            );
-                          },
+                              ],
+                            ),
+                          ),
                         ),
                       ),
                     ],
@@ -175,3 +158,274 @@ class AppearanceSettingsView extends ConsumerWidget {
     );
   }
 }
+
+class ThemeOptionsView extends ConsumerStatefulWidget {
+  const ThemeOptionsView({
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  ConsumerState<ThemeOptionsView> createState() => _ThemeOptionsView();
+}
+
+class _ThemeOptionsView extends ConsumerState<ThemeOptionsView> {
+  late String _selectedTheme;
+
+  @override
+  void initState() {
+    _selectedTheme =
+        DB.instance.get<dynamic>(boxName: DB.boxNameTheme, key: "colorScheme")
+                as String? ??
+            "light";
+
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        MaterialButton(
+          splashColor: Colors.transparent,
+          hoverColor: Colors.transparent,
+          padding: const EdgeInsets.all(0),
+          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(
+              Constants.size.circularBorderRadius,
+            ),
+          ),
+          onPressed: () {
+            DB.instance.put<dynamic>(
+              boxName: DB.boxNameTheme,
+              key: "colorScheme",
+              value: ThemeType.light.name,
+            );
+            ref.read(colorThemeProvider.state).state =
+                StackColors.fromStackColorTheme(
+              LightColors(),
+            );
+
+            setState(() {
+              _selectedTheme = "light";
+            });
+          },
+          child: SizedBox(
+            width: 200,
+            child: Column(
+              mainAxisSize: MainAxisSize.min,
+              children: [
+                Row(
+                  children: [
+                    SizedBox(
+                      width: 10,
+                      height: 10,
+                      child: Radio(
+                        activeColor: Theme.of(context)
+                            .extension<StackColors>()!
+                            .radioButtonIconEnabled,
+                        value: "light",
+                        groupValue: _selectedTheme,
+                        onChanged: (newValue) {
+                          if (newValue is String && newValue == "light") {
+                            DB.instance.put<dynamic>(
+                              boxName: DB.boxNameTheme,
+                              key: "colorScheme",
+                              value: ThemeType.light.name,
+                            );
+                            ref.read(colorThemeProvider.state).state =
+                                StackColors.fromStackColorTheme(
+                              LightColors(),
+                            );
+
+                            setState(() {
+                              _selectedTheme = "light";
+                            });
+                          }
+                        },
+                      ),
+                    ),
+                    const SizedBox(
+                      width: 14,
+                    ),
+                    Text(
+                      "Light",
+                      style:
+                          STextStyles.desktopTextExtraSmall(context).copyWith(
+                        color: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textDark2,
+                      ),
+                    ),
+                  ],
+                ),
+              ],
+            ),
+          ),
+        ),
+        const SizedBox(
+          height: 10,
+        ),
+        MaterialButton(
+          splashColor: Colors.transparent,
+          hoverColor: Colors.transparent,
+          padding: const EdgeInsets.all(0),
+          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(
+              Constants.size.circularBorderRadius,
+            ),
+          ),
+          onPressed: () {
+            DB.instance.put<dynamic>(
+              boxName: DB.boxNameTheme,
+              key: "colorScheme",
+              value: ThemeType.oceanBreeze.name,
+            );
+            ref.read(colorThemeProvider.state).state =
+                StackColors.fromStackColorTheme(
+              OceanBreezeColors(),
+            );
+
+            setState(() {
+              _selectedTheme = "oceanBreeze";
+            });
+          },
+          child: SizedBox(
+            width: 200,
+            child: Column(
+              mainAxisSize: MainAxisSize.min,
+              children: [
+                Row(
+                  children: [
+                    SizedBox(
+                      width: 10,
+                      height: 10,
+                      child: Radio(
+                        activeColor: Theme.of(context)
+                            .extension<StackColors>()!
+                            .radioButtonIconEnabled,
+                        value: "oceanBreeze",
+                        groupValue: _selectedTheme,
+                        onChanged: (newValue) {
+                          if (newValue is String && newValue == "oceanBreeze") {
+                            DB.instance.put<dynamic>(
+                              boxName: DB.boxNameTheme,
+                              key: "colorScheme",
+                              value: ThemeType.oceanBreeze.name,
+                            );
+                            ref.read(colorThemeProvider.state).state =
+                                StackColors.fromStackColorTheme(
+                              OceanBreezeColors(),
+                            );
+
+                            setState(() {
+                              _selectedTheme = "oceanBreeze";
+                            });
+                          }
+                        },
+                      ),
+                    ),
+                    const SizedBox(
+                      width: 14,
+                    ),
+                    Text(
+                      "Ocean Breeze",
+                      style:
+                          STextStyles.desktopTextExtraSmall(context).copyWith(
+                        color: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textDark2,
+                      ),
+                    ),
+                  ],
+                ),
+              ],
+            ),
+          ),
+        ),
+        const SizedBox(
+          height: 10,
+        ),
+        MaterialButton(
+          splashColor: Colors.transparent,
+          hoverColor: Colors.transparent,
+          padding: const EdgeInsets.all(0),
+          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(
+              Constants.size.circularBorderRadius,
+            ),
+          ),
+          onPressed: () {
+            DB.instance.put<dynamic>(
+              boxName: DB.boxNameTheme,
+              key: "colorScheme",
+              value: ThemeType.dark.name,
+            );
+            ref.read(colorThemeProvider.state).state =
+                StackColors.fromStackColorTheme(
+              DarkColors(),
+            );
+
+            setState(() {
+              _selectedTheme = "dark";
+            });
+          },
+          child: SizedBox(
+            width: 200,
+            child: Column(
+              mainAxisSize: MainAxisSize.min,
+              children: [
+                Row(
+                  children: [
+                    SizedBox(
+                      width: 10,
+                      height: 10,
+                      child: Radio(
+                        activeColor: Theme.of(context)
+                            .extension<StackColors>()!
+                            .radioButtonIconEnabled,
+                        value: "dark",
+                        groupValue: _selectedTheme,
+                        onChanged: (newValue) {
+                          if (newValue is String && newValue == "dark") {
+                            DB.instance.put<dynamic>(
+                              boxName: DB.boxNameTheme,
+                              key: "colorScheme",
+                              value: ThemeType.dark.name,
+                            );
+                            ref.read(colorThemeProvider.state).state =
+                                StackColors.fromStackColorTheme(
+                              DarkColors(),
+                            );
+
+                            setState(() {
+                              _selectedTheme = "dark";
+                            });
+                          }
+                        },
+                      ),
+                    ),
+                    const SizedBox(
+                      width: 14,
+                    ),
+                    Text(
+                      "Dark",
+                      style:
+                          STextStyles.desktopTextExtraSmall(context).copyWith(
+                        color: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textDark2,
+                      ),
+                    ),
+                  ],
+                ),
+              ],
+            ),
+          ),
+        ),
+      ],
+    );
+  }
+}

From 9956a497df081a54a67a90ae68f93ee5d6e32cc3 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Fri, 18 Nov 2022 13:26:17 -0700
Subject: [PATCH 043/100] ocean breeze shadow color fix

---
 lib/utilities/theme/ocean_breeze_colors.dart | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/utilities/theme/ocean_breeze_colors.dart b/lib/utilities/theme/ocean_breeze_colors.dart
index 1eb06e068..665eaa0c3 100644
--- a/lib/utilities/theme/ocean_breeze_colors.dart
+++ b/lib/utilities/theme/ocean_breeze_colors.dart
@@ -24,7 +24,7 @@ class OceanBreezeColors extends StackColorTheme {
   Color get accentColorDark => const Color(0xFF227386);
 
   @override
-  Color get shadow => const Color(0xFF388192);
+  Color get shadow => const Color(0x0F2D3132);
 
   @override
   Color get textDark => const Color(0xFF232323);

From e665926b1bc229e6abee16bdda38debe242191e4 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 14:59:53 -0600
Subject: [PATCH 044/100] firo anonymize navigation fix

---
 .../wallet_view/desktop_wallet_view.dart      | 47 +++++++++++++++++--
 1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
index d08864eee..85dde4aba 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
@@ -193,6 +193,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
     if (publicBalance <= Decimal.zero) {
       shouldPop = true;
       if (mounted) {
+        Navigator.of(context, rootNavigator: true).pop();
         Navigator.of(context).popUntil(
           ModalRoute.withName(DesktopWalletView.routeName),
         );
@@ -211,6 +212,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
       await firoWallet.anonymizeAllPublicFunds();
       shouldPop = true;
       if (mounted) {
+        Navigator.of(context, rootNavigator: true).pop();
         Navigator.of(context).popUntil(
           ModalRoute.withName(DesktopWalletView.routeName),
         );
@@ -225,14 +227,53 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
     } catch (e) {
       shouldPop = true;
       if (mounted) {
+        Navigator.of(context, rootNavigator: true).pop();
         Navigator.of(context).popUntil(
           ModalRoute.withName(DesktopWalletView.routeName),
         );
         await showDialog<dynamic>(
           context: context,
-          builder: (_) => StackOkDialog(
-            title: "Anonymize all failed",
-            message: "Reason: $e",
+          builder: (_) => DesktopDialog(
+            maxWidth: 400,
+            maxHeight: 300,
+            child: Padding(
+              padding: const EdgeInsets.all(24),
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
+                children: [
+                  Text(
+                    "Anonymize all failed",
+                    style: STextStyles.desktopH3(context),
+                  ),
+                  const Spacer(
+                    flex: 1,
+                  ),
+                  Text(
+                    "Reason: $e",
+                    style: STextStyles.desktopTextSmall(context),
+                  ),
+                  const Spacer(
+                    flex: 2,
+                  ),
+                  Row(
+                    children: [
+                      const Spacer(),
+                      const SizedBox(
+                        width: 16,
+                      ),
+                      Expanded(
+                        child: PrimaryButton(
+                          label: "Ok",
+                          buttonHeight: ButtonHeight.l,
+                          onPressed:
+                              Navigator.of(context, rootNavigator: true).pop,
+                        ),
+                      ),
+                    ],
+                  )
+                ],
+              ),
+            ),
           ),
         );
       }

From 9ba83f36eb480ff0dab6af8ca4a2ebed5d37642d Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 16:05:15 -0600
Subject: [PATCH 045/100] desktop exchange rate toggle style

---
 assets/svg/lock-open.svg                      |   3 +
 .../sub_widgets/rate_type_toggle.dart         | 115 +++++++++++++-----
 pubspec.yaml                                  |   1 +
 3 files changed, 88 insertions(+), 31 deletions(-)
 create mode 100644 assets/svg/lock-open.svg

diff --git a/assets/svg/lock-open.svg b/assets/svg/lock-open.svg
new file mode 100644
index 000000000..f2b00f341
--- /dev/null
+++ b/assets/svg/lock-open.svg
@@ -0,0 +1,3 @@
+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M7 1.75C5.79141 1.75 4.8125 2.72945 4.8125 3.9375V5.25H11.375C12.3402 5.25 13.125 6.03477 13.125 7V12.25C13.125 13.2152 12.3402 14 11.375 14H2.625C1.6584 14 0.875 13.2152 0.875 12.25V7C0.875 6.03477 1.6584 5.25 2.625 5.25H3.0625V3.9375C3.0625 1.76285 4.82617 0 7 0C8.57227 0 9.92578 0.921211 10.5574 2.24957C10.7652 2.68598 10.5793 3.20742 10.1199 3.41523C9.68242 3.62305 9.18476 3.43711 8.97695 2.99961C8.62422 2.25941 7.87227 1.75 7 1.75ZM7.875 10.5C8.35898 10.5 8.75 10.109 8.75 9.625C8.75 9.14102 8.35898 8.75 7.875 8.75H6.125C5.64102 8.75 5.25 9.14102 5.25 9.625C5.25 10.109 5.64102 10.5 6.125 10.5H7.875Z" fill="#0056D2"/>
+</svg>
diff --git a/lib/pages/exchange_view/sub_widgets/rate_type_toggle.dart b/lib/pages/exchange_view/sub_widgets/rate_type_toggle.dart
index 31460c75f..9697710e8 100644
--- a/lib/pages/exchange_view/sub_widgets/rate_type_toggle.dart
+++ b/lib/pages/exchange_view/sub_widgets/rate_type_toggle.dart
@@ -7,8 +7,8 @@ import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
 import 'package:stackwallet/widgets/rounded_container.dart';
-import 'package:stackwallet/widgets/rounded_white_container.dart';
 
 class RateTypeToggle extends ConsumerWidget {
   const RateTypeToggle({
@@ -21,12 +21,17 @@ class RateTypeToggle extends ConsumerWidget {
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     debugPrint("BUILD: $runtimeType");
+    final isDesktop = Util.isDesktop;
+
     final estimated = ref.watch(prefsChangeNotifierProvider
             .select((value) => value.exchangeRateType)) ==
         ExchangeRateType.estimated;
 
-    return RoundedWhiteContainer(
+    return RoundedContainer(
       padding: const EdgeInsets.all(0),
+      color: isDesktop
+          ? Theme.of(context).extension<StackColors>()!.buttonBackSecondary
+          : Theme.of(context).extension<StackColors>()!.popupBG,
       child: Row(
         children: [
           Expanded(
@@ -39,6 +44,9 @@ class RateTypeToggle extends ConsumerWidget {
                 }
               },
               child: RoundedContainer(
+                padding: isDesktop
+                    ? const EdgeInsets.all(17)
+                    : const EdgeInsets.all(0),
                 color: estimated
                     ? Theme.of(context)
                         .extension<StackColors>()!
@@ -48,29 +56,50 @@ class RateTypeToggle extends ConsumerWidget {
                   mainAxisAlignment: MainAxisAlignment.center,
                   children: [
                     SvgPicture.asset(
-                      Assets.svg.lock,
+                      Assets.svg.lockOpen,
                       width: 12,
                       height: 14,
-                      color: estimated
-                          ? Theme.of(context).extension<StackColors>()!.textDark
-                          : Theme.of(context)
-                              .extension<StackColors>()!
-                              .textSubtitle1,
+                      color: isDesktop
+                          ? estimated
+                              ? Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .accentColorBlue
+                              : Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .buttonTextSecondary
+                          : estimated
+                              ? Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textDark
+                              : Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textSubtitle1,
                     ),
                     const SizedBox(
                       width: 5,
                     ),
                     Text(
                       "Estimate rate",
-                      style: STextStyles.smallMed12(context).copyWith(
-                        color: estimated
-                            ? Theme.of(context)
-                                .extension<StackColors>()!
-                                .textDark
-                            : Theme.of(context)
-                                .extension<StackColors>()!
-                                .textSubtitle1,
-                      ),
+                      style: isDesktop
+                          ? STextStyles.desktopTextExtraExtraSmall(context)
+                              .copyWith(
+                              color: estimated
+                                  ? Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .accentColorBlue
+                                  : Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .buttonTextSecondary,
+                            )
+                          : STextStyles.smallMed12(context).copyWith(
+                              color: estimated
+                                  ? Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark
+                                  : Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textSubtitle1,
+                            ),
                     ),
                   ],
                 ),
@@ -87,6 +116,9 @@ class RateTypeToggle extends ConsumerWidget {
                 }
               },
               child: RoundedContainer(
+                padding: isDesktop
+                    ? const EdgeInsets.all(17)
+                    : const EdgeInsets.all(0),
                 color: !estimated
                     ? Theme.of(context)
                         .extension<StackColors>()!
@@ -99,26 +131,47 @@ class RateTypeToggle extends ConsumerWidget {
                       Assets.svg.lock,
                       width: 12,
                       height: 14,
-                      color: !estimated
-                          ? Theme.of(context).extension<StackColors>()!.textDark
-                          : Theme.of(context)
-                              .extension<StackColors>()!
-                              .textSubtitle1,
+                      color: isDesktop
+                          ? !estimated
+                              ? Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .accentColorBlue
+                              : Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .buttonTextSecondary
+                          : !estimated
+                              ? Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textDark
+                              : Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textSubtitle1,
                     ),
                     const SizedBox(
                       width: 5,
                     ),
                     Text(
                       "Fixed rate",
-                      style: STextStyles.smallMed12(context).copyWith(
-                        color: !estimated
-                            ? Theme.of(context)
-                                .extension<StackColors>()!
-                                .textDark
-                            : Theme.of(context)
-                                .extension<StackColors>()!
-                                .textSubtitle1,
-                      ),
+                      style: isDesktop
+                          ? STextStyles.desktopTextExtraExtraSmall(context)
+                              .copyWith(
+                              color: !estimated
+                                  ? Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .accentColorBlue
+                                  : Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .buttonTextSecondary,
+                            )
+                          : STextStyles.smallMed12(context).copyWith(
+                              color: !estimated
+                                  ? Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark
+                                  : Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textSubtitle1,
+                            ),
                     ),
                   ],
                 ),
diff --git a/pubspec.yaml b/pubspec.yaml
index 6a721c5c1..e8f417586 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -228,6 +228,7 @@ flutter:
     - assets/svg/chevron-down.svg
     - assets/svg/chevron-up.svg
     - assets/svg/lock-keyhole.svg
+    - assets/svg/lock-open.svg
     - assets/svg/rotate-exclamation.svg
     - assets/svg/folder-down.svg
     - assets/svg/network-wired.svg

From 16113fd1d52319b855cb6e38044da84f810feb7a Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 16:05:46 -0600
Subject: [PATCH 046/100] desktop exchange provider options dropdown style

---
 .../exchange_provider_options.dart            | 706 ++++++++++--------
 1 file changed, 379 insertions(+), 327 deletions(-)

diff --git a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart
index 2113e199c..4dd768403 100644
--- a/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart
+++ b/lib/pages/exchange_view/sub_widgets/exchange_provider_options.dart
@@ -15,7 +15,9 @@ import 'package:stackwallet/utilities/format.dart';
 import 'package:stackwallet/utilities/logger.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
 import 'package:stackwallet/widgets/animated_text.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 
 class ExchangeProviderOptions extends ConsumerWidget {
@@ -38,353 +40,403 @@ class ExchangeProviderOptions extends ConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
+    final isDesktop = Util.isDesktop;
     return RoundedWhiteContainer(
+      padding: isDesktop ? const EdgeInsets.all(0) : const EdgeInsets.all(12),
+      borderColor: isDesktop
+          ? Theme.of(context).extension<StackColors>()!.background
+          : null,
       child: Column(
         children: [
-          GestureDetector(
-            onTap: () {
-              if (ref.read(currentExchangeNameStateProvider.state).state !=
-                  ChangeNowExchange.exchangeName) {
-                ref.read(currentExchangeNameStateProvider.state).state =
-                    ChangeNowExchange.exchangeName;
-                ref.read(exchangeFormStateProvider).exchange =
-                    Exchange.fromName(
-                        ref.read(currentExchangeNameStateProvider.state).state);
-              }
-            },
-            child: Container(
-              color: Colors.transparent,
-              child: Row(
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  SizedBox(
-                    width: 20,
-                    height: 20,
-                    child: Radio(
-                      activeColor: Theme.of(context)
-                          .extension<StackColors>()!
-                          .radioButtonIconEnabled,
-                      value: ChangeNowExchange.exchangeName,
-                      groupValue: ref
-                          .watch(currentExchangeNameStateProvider.state)
-                          .state,
-                      onChanged: (value) {
-                        if (value is String) {
-                          ref
-                              .read(currentExchangeNameStateProvider.state)
-                              .state = value;
-                          ref.read(exchangeFormStateProvider).exchange =
-                              Exchange.fromName(ref
+          ConditionalParent(
+            condition: isDesktop,
+            builder: (child) => MouseRegion(
+              cursor: SystemMouseCursors.click,
+              child: child,
+            ),
+            child: GestureDetector(
+              onTap: () {
+                if (ref.read(currentExchangeNameStateProvider.state).state !=
+                    ChangeNowExchange.exchangeName) {
+                  ref.read(currentExchangeNameStateProvider.state).state =
+                      ChangeNowExchange.exchangeName;
+                  ref.read(exchangeFormStateProvider).exchange =
+                      Exchange.fromName(ref
+                          .read(currentExchangeNameStateProvider.state)
+                          .state);
+                }
+              },
+              child: Container(
+                color: Colors.transparent,
+                child: Padding(
+                  padding: isDesktop
+                      ? const EdgeInsets.all(16)
+                      : const EdgeInsets.all(0),
+                  child: Row(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: [
+                      SizedBox(
+                        width: 20,
+                        height: 20,
+                        child: Radio(
+                          activeColor: Theme.of(context)
+                              .extension<StackColors>()!
+                              .radioButtonIconEnabled,
+                          value: ChangeNowExchange.exchangeName,
+                          groupValue: ref
+                              .watch(currentExchangeNameStateProvider.state)
+                              .state,
+                          onChanged: (value) {
+                            if (value is String) {
+                              ref
                                   .read(currentExchangeNameStateProvider.state)
-                                  .state);
-                        }
-                      },
-                    ),
-                  ),
-                  const SizedBox(
-                    width: 14,
-                  ),
-                  SvgPicture.asset(
-                    Assets.exchange.changeNow,
-                    width: 24,
-                    height: 24,
-                  ),
-                  const SizedBox(
-                    width: 10,
-                  ),
-                  Expanded(
-                    child: Column(
-                      mainAxisAlignment: MainAxisAlignment.start,
-                      mainAxisSize: MainAxisSize.min,
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      children: [
-                        Text(
-                          ChangeNowExchange.exchangeName,
-                          style: STextStyles.titleBold12(context).copyWith(
-                            color: Theme.of(context)
-                                .extension<StackColors>()!
-                                .textDark2,
-                          ),
+                                  .state = value;
+                              ref.read(exchangeFormStateProvider).exchange =
+                                  Exchange.fromName(ref
+                                      .read(currentExchangeNameStateProvider
+                                          .state)
+                                      .state);
+                            }
+                          },
                         ),
-                        if (from != null &&
-                            to != null &&
-                            toAmount != null &&
-                            toAmount! > Decimal.zero &&
-                            fromAmount != null &&
-                            fromAmount! > Decimal.zero)
-                          FutureBuilder(
-                            future: ChangeNowExchange().getEstimate(
-                              from!,
-                              to!,
-                              reversed ? toAmount! : fromAmount!,
-                              fixedRate,
-                              reversed,
+                      ),
+                      const SizedBox(
+                        width: 14,
+                      ),
+                      SvgPicture.asset(
+                        Assets.exchange.changeNow,
+                        width: isDesktop ? 32 : 24,
+                        height: isDesktop ? 32 : 24,
+                      ),
+                      const SizedBox(
+                        width: 10,
+                      ),
+                      Expanded(
+                        child: Column(
+                          mainAxisAlignment: MainAxisAlignment.start,
+                          mainAxisSize: MainAxisSize.min,
+                          crossAxisAlignment: CrossAxisAlignment.start,
+                          children: [
+                            Text(
+                              ChangeNowExchange.exchangeName,
+                              style: STextStyles.titleBold12(context).copyWith(
+                                color: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textDark2,
+                              ),
                             ),
-                            builder: (context,
-                                AsyncSnapshot<ExchangeResponse<Estimate>>
-                                    snapshot) {
-                              if (snapshot.connectionState ==
-                                      ConnectionState.done &&
-                                  snapshot.hasData) {
-                                final estimate = snapshot.data?.value;
-                                if (estimate != null) {
-                                  Decimal rate;
-                                  if (estimate.reversed) {
-                                    rate =
-                                        (toAmount! / estimate.estimatedAmount)
+                            if (from != null &&
+                                to != null &&
+                                toAmount != null &&
+                                toAmount! > Decimal.zero &&
+                                fromAmount != null &&
+                                fromAmount! > Decimal.zero)
+                              FutureBuilder(
+                                future: ChangeNowExchange().getEstimate(
+                                  from!,
+                                  to!,
+                                  reversed ? toAmount! : fromAmount!,
+                                  fixedRate,
+                                  reversed,
+                                ),
+                                builder: (context,
+                                    AsyncSnapshot<ExchangeResponse<Estimate>>
+                                        snapshot) {
+                                  if (snapshot.connectionState ==
+                                          ConnectionState.done &&
+                                      snapshot.hasData) {
+                                    final estimate = snapshot.data?.value;
+                                    if (estimate != null) {
+                                      Decimal rate;
+                                      if (estimate.reversed) {
+                                        rate = (toAmount! /
+                                                estimate.estimatedAmount)
                                             .toDecimal(
                                                 scaleOnInfinitePrecision: 12);
+                                      } else {
+                                        rate = (estimate.estimatedAmount /
+                                                fromAmount!)
+                                            .toDecimal(
+                                                scaleOnInfinitePrecision: 12);
+                                      }
+                                      return Text(
+                                        "1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed(
+                                          value: rate,
+                                          locale: ref.watch(
+                                            localeServiceChangeNotifierProvider
+                                                .select(
+                                                    (value) => value.locale),
+                                          ),
+                                          decimalPlaces: to!.toUpperCase() ==
+                                                  Coin.monero.ticker
+                                                      .toUpperCase()
+                                              ? Constants.decimalPlacesMonero
+                                              : Constants.decimalPlaces,
+                                        )} ${to!.toUpperCase()}",
+                                        style:
+                                            STextStyles.itemSubtitle12(context)
+                                                .copyWith(
+                                          color: Theme.of(context)
+                                              .extension<StackColors>()!
+                                              .textSubtitle1,
+                                        ),
+                                      );
+                                    } else {
+                                      Logging.instance.log(
+                                        "$runtimeType failed to fetch rate for ChangeNOW: ${snapshot.data}",
+                                        level: LogLevel.Warning,
+                                      );
+                                      return Text(
+                                        "Failed to fetch rate",
+                                        style:
+                                            STextStyles.itemSubtitle12(context)
+                                                .copyWith(
+                                          color: Theme.of(context)
+                                              .extension<StackColors>()!
+                                              .textSubtitle1,
+                                        ),
+                                      );
+                                    }
                                   } else {
-                                    rate =
-                                        (estimate.estimatedAmount / fromAmount!)
-                                            .toDecimal(
-                                                scaleOnInfinitePrecision: 12);
-                                  }
-                                  return Text(
-                                    "1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed(
-                                      value: rate,
-                                      locale: ref.watch(
-                                        localeServiceChangeNotifierProvider
-                                            .select((value) => value.locale),
+                                    return AnimatedText(
+                                      stringsToLoopThrough: const [
+                                        "Loading",
+                                        "Loading.",
+                                        "Loading..",
+                                        "Loading...",
+                                      ],
+                                      style: STextStyles.itemSubtitle12(context)
+                                          .copyWith(
+                                        color: Theme.of(context)
+                                            .extension<StackColors>()!
+                                            .textSubtitle1,
                                       ),
-                                      decimalPlaces: to!.toUpperCase() ==
-                                              Coin.monero.ticker.toUpperCase()
-                                          ? Constants.decimalPlacesMonero
-                                          : Constants.decimalPlaces,
-                                    )} ${to!.toUpperCase()}",
-                                    style: STextStyles.itemSubtitle12(context)
-                                        .copyWith(
-                                      color: Theme.of(context)
-                                          .extension<StackColors>()!
-                                          .textSubtitle1,
-                                    ),
-                                  );
-                                } else {
-                                  Logging.instance.log(
-                                    "$runtimeType failed to fetch rate for ChangeNOW: ${snapshot.data}",
-                                    level: LogLevel.Warning,
-                                  );
-                                  return Text(
-                                    "Failed to fetch rate",
-                                    style: STextStyles.itemSubtitle12(context)
-                                        .copyWith(
-                                      color: Theme.of(context)
-                                          .extension<StackColors>()!
-                                          .textSubtitle1,
-                                    ),
-                                  );
-                                }
-                              } else {
-                                return AnimatedText(
-                                  stringsToLoopThrough: const [
-                                    "Loading",
-                                    "Loading.",
-                                    "Loading..",
-                                    "Loading...",
-                                  ],
-                                  style: STextStyles.itemSubtitle12(context)
-                                      .copyWith(
-                                    color: Theme.of(context)
-                                        .extension<StackColors>()!
-                                        .textSubtitle1,
-                                  ),
-                                );
-                              }
-                            },
-                          ),
-                        if (!(from != null &&
-                            to != null &&
-                            toAmount != null &&
-                            toAmount! > Decimal.zero &&
-                            fromAmount != null &&
-                            fromAmount! > Decimal.zero))
-                          Text(
-                            "n/a",
-                            style: STextStyles.itemSubtitle12(context).copyWith(
-                              color: Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .textSubtitle1,
-                            ),
-                          ),
-                      ],
-                    ),
+                                    );
+                                  }
+                                },
+                              ),
+                            if (!(from != null &&
+                                to != null &&
+                                toAmount != null &&
+                                toAmount! > Decimal.zero &&
+                                fromAmount != null &&
+                                fromAmount! > Decimal.zero))
+                              Text(
+                                "n/a",
+                                style: STextStyles.itemSubtitle12(context)
+                                    .copyWith(
+                                  color: Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textSubtitle1,
+                                ),
+                              ),
+                          ],
+                        ),
+                      ),
+                    ],
                   ),
-                ],
+                ),
               ),
             ),
           ),
-          const SizedBox(
-            height: 16,
-          ),
-          GestureDetector(
-            onTap: () {
-              if (ref.read(currentExchangeNameStateProvider.state).state !=
-                  SimpleSwapExchange.exchangeName) {
-                ref.read(currentExchangeNameStateProvider.state).state =
-                    SimpleSwapExchange.exchangeName;
-                ref.read(exchangeFormStateProvider).exchange =
-                    Exchange.fromName(
-                        ref.read(currentExchangeNameStateProvider.state).state);
-              }
-            },
-            child: Container(
-              color: Colors.transparent,
-              child: Row(
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  SizedBox(
-                    width: 20,
-                    height: 20,
-                    child: Radio(
-                      activeColor: Theme.of(context)
-                          .extension<StackColors>()!
-                          .radioButtonIconEnabled,
-                      value: SimpleSwapExchange.exchangeName,
-                      groupValue: ref
-                          .watch(currentExchangeNameStateProvider.state)
-                          .state,
-                      onChanged: (value) {
-                        if (value is String) {
-                          ref
-                              .read(currentExchangeNameStateProvider.state)
-                              .state = value;
-                          ref.read(exchangeFormStateProvider).exchange =
-                              Exchange.fromName(ref
+          if (isDesktop)
+            Container(
+              height: 1,
+              color: Theme.of(context).extension<StackColors>()!.background,
+            ),
+          if (!isDesktop)
+            const SizedBox(
+              height: 16,
+            ),
+          ConditionalParent(
+            condition: isDesktop,
+            builder: (child) => MouseRegion(
+              cursor: SystemMouseCursors.click,
+              child: child,
+            ),
+            child: GestureDetector(
+              onTap: () {
+                if (ref.read(currentExchangeNameStateProvider.state).state !=
+                    SimpleSwapExchange.exchangeName) {
+                  ref.read(currentExchangeNameStateProvider.state).state =
+                      SimpleSwapExchange.exchangeName;
+                  ref.read(exchangeFormStateProvider).exchange =
+                      Exchange.fromName(ref
+                          .read(currentExchangeNameStateProvider.state)
+                          .state);
+                }
+              },
+              child: Container(
+                color: Colors.transparent,
+                child: Padding(
+                  padding: isDesktop
+                      ? const EdgeInsets.all(16)
+                      : const EdgeInsets.all(0),
+                  child: Row(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: [
+                      SizedBox(
+                        width: 20,
+                        height: 20,
+                        child: Radio(
+                          activeColor: Theme.of(context)
+                              .extension<StackColors>()!
+                              .radioButtonIconEnabled,
+                          value: SimpleSwapExchange.exchangeName,
+                          groupValue: ref
+                              .watch(currentExchangeNameStateProvider.state)
+                              .state,
+                          onChanged: (value) {
+                            if (value is String) {
+                              ref
                                   .read(currentExchangeNameStateProvider.state)
-                                  .state);
-                        }
-                      },
-                    ),
-                  ),
-                  const SizedBox(
-                    width: 14,
-                  ),
-                  SvgPicture.asset(
-                    Assets.exchange.simpleSwap,
-                    width: 24,
-                    height: 24,
-                  ),
-                  const SizedBox(
-                    width: 10,
-                  ),
-                  Expanded(
-                    child: Column(
-                      mainAxisAlignment: MainAxisAlignment.start,
-                      mainAxisSize: MainAxisSize.min,
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      children: [
-                        Text(
-                          SimpleSwapExchange.exchangeName,
-                          style: STextStyles.titleBold12(context).copyWith(
-                            color: Theme.of(context)
-                                .extension<StackColors>()!
-                                .textDark2,
-                          ),
+                                  .state = value;
+                              ref.read(exchangeFormStateProvider).exchange =
+                                  Exchange.fromName(ref
+                                      .read(currentExchangeNameStateProvider
+                                          .state)
+                                      .state);
+                            }
+                          },
                         ),
-                        if (from != null &&
-                            to != null &&
-                            toAmount != null &&
-                            toAmount! > Decimal.zero &&
-                            fromAmount != null &&
-                            fromAmount! > Decimal.zero)
-                          FutureBuilder(
-                            future: SimpleSwapExchange().getEstimate(
-                              from!,
-                              to!,
-                              // reversed ? toAmount! : fromAmount!,
-                              fromAmount!,
-                              fixedRate,
-                              // reversed,
-                              false,
+                      ),
+                      const SizedBox(
+                        width: 14,
+                      ),
+                      SvgPicture.asset(
+                        Assets.exchange.simpleSwap,
+                        width: isDesktop ? 32 : 24,
+                        height: isDesktop ? 32 : 24,
+                      ),
+                      const SizedBox(
+                        width: 10,
+                      ),
+                      Expanded(
+                        child: Column(
+                          mainAxisAlignment: MainAxisAlignment.start,
+                          mainAxisSize: MainAxisSize.min,
+                          crossAxisAlignment: CrossAxisAlignment.start,
+                          children: [
+                            Text(
+                              SimpleSwapExchange.exchangeName,
+                              style: STextStyles.titleBold12(context).copyWith(
+                                color: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textDark2,
+                              ),
                             ),
-                            builder: (context,
-                                AsyncSnapshot<ExchangeResponse<Estimate>>
-                                    snapshot) {
-                              if (snapshot.connectionState ==
-                                      ConnectionState.done &&
-                                  snapshot.hasData) {
-                                final estimate = snapshot.data?.value;
-                                if (estimate != null) {
-                                  Decimal rate = (estimate.estimatedAmount /
-                                          fromAmount!)
-                                      .toDecimal(scaleOnInfinitePrecision: 12);
+                            if (from != null &&
+                                to != null &&
+                                toAmount != null &&
+                                toAmount! > Decimal.zero &&
+                                fromAmount != null &&
+                                fromAmount! > Decimal.zero)
+                              FutureBuilder(
+                                future: SimpleSwapExchange().getEstimate(
+                                  from!,
+                                  to!,
+                                  // reversed ? toAmount! : fromAmount!,
+                                  fromAmount!,
+                                  fixedRate,
+                                  // reversed,
+                                  false,
+                                ),
+                                builder: (context,
+                                    AsyncSnapshot<ExchangeResponse<Estimate>>
+                                        snapshot) {
+                                  if (snapshot.connectionState ==
+                                          ConnectionState.done &&
+                                      snapshot.hasData) {
+                                    final estimate = snapshot.data?.value;
+                                    if (estimate != null) {
+                                      Decimal rate = (estimate.estimatedAmount /
+                                              fromAmount!)
+                                          .toDecimal(
+                                              scaleOnInfinitePrecision: 12);
 
-                                  return Text(
-                                    "1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed(
-                                      value: rate,
-                                      locale: ref.watch(
-                                        localeServiceChangeNotifierProvider
-                                            .select((value) => value.locale),
+                                      return Text(
+                                        "1 ${from!.toUpperCase()} ~ ${Format.localizedStringAsFixed(
+                                          value: rate,
+                                          locale: ref.watch(
+                                            localeServiceChangeNotifierProvider
+                                                .select(
+                                                    (value) => value.locale),
+                                          ),
+                                          decimalPlaces: to!.toUpperCase() ==
+                                                  Coin.monero.ticker
+                                                      .toUpperCase()
+                                              ? Constants.decimalPlacesMonero
+                                              : Constants.decimalPlaces,
+                                        )} ${to!.toUpperCase()}",
+                                        style:
+                                            STextStyles.itemSubtitle12(context)
+                                                .copyWith(
+                                          color: Theme.of(context)
+                                              .extension<StackColors>()!
+                                              .textSubtitle1,
+                                        ),
+                                      );
+                                    } else {
+                                      Logging.instance.log(
+                                        "$runtimeType failed to fetch rate for SimpleSwap: ${snapshot.data}",
+                                        level: LogLevel.Warning,
+                                      );
+                                      return Text(
+                                        "Failed to fetch rate",
+                                        style:
+                                            STextStyles.itemSubtitle12(context)
+                                                .copyWith(
+                                          color: Theme.of(context)
+                                              .extension<StackColors>()!
+                                              .textSubtitle1,
+                                        ),
+                                      );
+                                    }
+                                  } else {
+                                    return AnimatedText(
+                                      stringsToLoopThrough: const [
+                                        "Loading",
+                                        "Loading.",
+                                        "Loading..",
+                                        "Loading...",
+                                      ],
+                                      style: STextStyles.itemSubtitle12(context)
+                                          .copyWith(
+                                        color: Theme.of(context)
+                                            .extension<StackColors>()!
+                                            .textSubtitle1,
                                       ),
-                                      decimalPlaces: to!.toUpperCase() ==
-                                              Coin.monero.ticker.toUpperCase()
-                                          ? Constants.decimalPlacesMonero
-                                          : Constants.decimalPlaces,
-                                    )} ${to!.toUpperCase()}",
-                                    style: STextStyles.itemSubtitle12(context)
-                                        .copyWith(
-                                      color: Theme.of(context)
-                                          .extension<StackColors>()!
-                                          .textSubtitle1,
-                                    ),
-                                  );
-                                } else {
-                                  Logging.instance.log(
-                                    "$runtimeType failed to fetch rate for SimpleSwap: ${snapshot.data}",
-                                    level: LogLevel.Warning,
-                                  );
-                                  return Text(
-                                    "Failed to fetch rate",
-                                    style: STextStyles.itemSubtitle12(context)
-                                        .copyWith(
-                                      color: Theme.of(context)
-                                          .extension<StackColors>()!
-                                          .textSubtitle1,
-                                    ),
-                                  );
-                                }
-                              } else {
-                                return AnimatedText(
-                                  stringsToLoopThrough: const [
-                                    "Loading",
-                                    "Loading.",
-                                    "Loading..",
-                                    "Loading...",
-                                  ],
-                                  style: STextStyles.itemSubtitle12(context)
-                                      .copyWith(
-                                    color: Theme.of(context)
-                                        .extension<StackColors>()!
-                                        .textSubtitle1,
-                                  ),
-                                );
-                              }
-                            },
-                          ),
-                        // if (!(from != null &&
-                        //     to != null &&
-                        //     (reversed
-                        //         ? toAmount != null && toAmount! > Decimal.zero
-                        //         : fromAmount != null &&
-                        //             fromAmount! > Decimal.zero)))
-                        if (!(from != null &&
-                            to != null &&
-                            toAmount != null &&
-                            toAmount! > Decimal.zero &&
-                            fromAmount != null &&
-                            fromAmount! > Decimal.zero))
-                          Text(
-                            "n/a",
-                            style: STextStyles.itemSubtitle12(context).copyWith(
-                              color: Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .textSubtitle1,
-                            ),
-                          ),
-                      ],
-                    ),
+                                    );
+                                  }
+                                },
+                              ),
+                            // if (!(from != null &&
+                            //     to != null &&
+                            //     (reversed
+                            //         ? toAmount != null && toAmount! > Decimal.zero
+                            //         : fromAmount != null &&
+                            //             fromAmount! > Decimal.zero)))
+                            if (!(from != null &&
+                                to != null &&
+                                toAmount != null &&
+                                toAmount! > Decimal.zero &&
+                                fromAmount != null &&
+                                fromAmount! > Decimal.zero))
+                              Text(
+                                "n/a",
+                                style: STextStyles.itemSubtitle12(context)
+                                    .copyWith(
+                                  color: Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textSubtitle1,
+                                ),
+                              ),
+                          ],
+                        ),
+                      ),
+                    ],
                   ),
-                ],
+                ),
               ),
             ),
           ),

From 96453e90541ce78a9c7a2f6e57f81554fc1839c0 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 16:06:03 -0600
Subject: [PATCH 047/100] missing asset declaration

---
 lib/utilities/assets.dart | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart
index c423ec491..6fbe61005 100644
--- a/lib/utilities/assets.dart
+++ b/lib/utilities/assets.dart
@@ -107,6 +107,7 @@ class _SVG {
   String get swap => "assets/svg/swap.svg";
   String get downloadFolder => "assets/svg/folder-down.svg";
   String get lock => "assets/svg/lock-keyhole.svg";
+  String get lockOpen => "assets/svg/lock-open.svg";
   String get network => "assets/svg/network-wired.svg";
   String get networkWired => "assets/svg/network-wired-2.svg";
   String get addressBook => "assets/svg/address-book.svg";

From 3ae38c582bdcd70c9ab68560ef832a6a7aad3fdf Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 16:06:29 -0600
Subject: [PATCH 048/100] desktop exchange form layout

---
 lib/pages/exchange_view/exchange_form.dart | 194 ++++++++++++++-------
 1 file changed, 134 insertions(+), 60 deletions(-)

diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart
index 7b04f90b3..5ece5aba8 100644
--- a/lib/pages/exchange_view/exchange_form.dart
+++ b/lib/pages/exchange_view/exchange_form.dart
@@ -27,9 +27,12 @@ import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
 import 'package:stackwallet/utilities/logger.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/custom_loading_overlay.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/loading_indicator.dart';
+import 'package:stackwallet/widgets/rounded_container.dart';
 import 'package:stackwallet/widgets/stack_dialog.dart';
 import 'package:tuple/tuple.dart';
 
@@ -54,6 +57,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
 
   late final TextEditingController _sendController;
   late final TextEditingController _receiveController;
+  final isDesktop = Util.isDesktop;
   final FocusNode _sendFocusNode = FocusNode();
   final FocusNode _receiveFocusNode = FocusNode();
 
@@ -960,8 +964,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
             color: Theme.of(context).extension<StackColors>()!.textDark3,
           ),
         ),
-        const SizedBox(
-          height: 4,
+        SizedBox(
+          height: isDesktop ? 10 : 4,
         ),
         TextFormField(
           style: STextStyles.smallMed14(context).copyWith(
@@ -970,6 +974,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
           focusNode: _sendFocusNode,
           controller: _sendController,
           textAlign: TextAlign.right,
+          enableSuggestions: false,
+          autocorrect: false,
           onTap: () {
             if (_sendController.text == "-") {
               _sendController.text = "";
@@ -1100,68 +1106,122 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
             ),
           ),
         ),
-        const SizedBox(
-          height: 4,
+
+        SizedBox(
+          height: isDesktop ? 10 : 4,
         ),
-        Stack(
+        if (ref
+                .watch(
+                    exchangeFormStateProvider.select((value) => value.warning))
+                .isNotEmpty &&
+            !ref.watch(
+                exchangeFormStateProvider.select((value) => value.reversed)))
+          Text(
+            ref.watch(
+                exchangeFormStateProvider.select((value) => value.warning)),
+            style: STextStyles.errorSmall(context),
+          ),
+        Row(
+          crossAxisAlignment: CrossAxisAlignment.end,
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
           children: [
-            Positioned.fill(
-              child: Align(
-                alignment: Alignment.bottomLeft,
-                child: Text(
-                  "You will receive",
-                  style: STextStyles.itemSubtitle(context).copyWith(
-                    color:
-                        Theme.of(context).extension<StackColors>()!.textDark3,
-                  ),
+            Text(
+              "You will receive",
+              style: STextStyles.itemSubtitle(context).copyWith(
+                color: Theme.of(context).extension<StackColors>()!.textDark3,
+              ),
+            ),
+            ConditionalParent(
+              condition: isDesktop,
+              builder: (child) => MouseRegion(
+                cursor: SystemMouseCursors.click,
+                child: RoundedContainer(
+                  padding: const EdgeInsets.all(6),
+                  color: Theme.of(context)
+                      .extension<StackColors>()!
+                      .buttonBackSecondary,
+                  radiusMultiplier: 0.75,
+                  child: child,
                 ),
               ),
-            ),
-            Center(
-              child: Column(
-                children: [
-                  const SizedBox(
-                    height: 6,
+              child: GestureDetector(
+                onTap: () async {
+                  await _swap();
+                },
+                child: Padding(
+                  padding: const EdgeInsets.all(4),
+                  child: SvgPicture.asset(
+                    Assets.svg.swap,
+                    width: 20,
+                    height: 20,
+                    color: Theme.of(context)
+                        .extension<StackColors>()!
+                        .accentColorDark,
                   ),
-                  GestureDetector(
-                    onTap: () async {
-                      await _swap();
-                    },
-                    child: Padding(
-                      padding: const EdgeInsets.all(4),
-                      child: SvgPicture.asset(
-                        Assets.svg.swap,
-                        width: 20,
-                        height: 20,
-                        color: Theme.of(context)
-                            .extension<StackColors>()!
-                            .accentColorDark,
-                      ),
-                    ),
-                  ),
-                  const SizedBox(
-                    height: 6,
-                  ),
-                ],
-              ),
-            ),
-            Positioned.fill(
-              child: Align(
-                alignment: ref.watch(exchangeFormStateProvider
-                        .select((value) => value.reversed))
-                    ? Alignment.bottomRight
-                    : Alignment.topRight,
-                child: Text(
-                  ref.watch(exchangeFormStateProvider
-                      .select((value) => value.warning)),
-                  style: STextStyles.errorSmall(context),
                 ),
               ),
             ),
           ],
         ),
-        const SizedBox(
-          height: 4,
+        // Stack(
+        //   children: [
+        //     Positioned.fill(
+        //       child: Align(
+        //         alignment: Alignment.bottomLeft,
+        //         child: Text(
+        //           "You will receive",
+        //           style: STextStyles.itemSubtitle(context).copyWith(
+        //             color:
+        //                 Theme.of(context).extension<StackColors>()!.textDark3,
+        //           ),
+        //         ),
+        //       ),
+        //     ),
+        //     Center(
+        //       child: Column(
+        //         children: [
+        //           const SizedBox(
+        //             height: 6,
+        //           ),
+        //           GestureDetector(
+        //             onTap: () async {
+        //               await _swap();
+        //             },
+        //             child: Padding(
+        //               padding: const EdgeInsets.all(4),
+        //               child: SvgPicture.asset(
+        //                 Assets.svg.swap,
+        //                 width: 20,
+        //                 height: 20,
+        //                 color: Theme.of(context)
+        //                     .extension<StackColors>()!
+        //                     .accentColorDark,
+        //               ),
+        //             ),
+        //           ),
+        //           const SizedBox(
+        //             height: 6,
+        //           ),
+        //         ],
+        //       ),
+        //     ),
+        //     Positioned.fill(
+        //       child: Align(
+        //         alignment: ref.watch(exchangeFormStateProvider
+        //                 .select((value) => value.reversed))
+        //             ? Alignment.bottomRight
+        //             : Alignment.topRight,
+        //         child: Text(
+        //           ref.watch(exchangeFormStateProvider
+        //               .select((value) => value.warning)),
+        //           style: STextStyles.errorSmall(context),
+        //         ),
+        //       ),
+        //     ),
+        //   ],
+        // ),
+        SizedBox(
+          height: isDesktop ? 10 : 4,
         ),
         TextFormField(
           style: STextStyles.smallMed14(context).copyWith(
@@ -1169,6 +1229,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
           ),
           focusNode: _receiveFocusNode,
           controller: _receiveController,
+          enableSuggestions: false,
+          autocorrect: false,
           readOnly: ref.watch(prefsChangeNotifierProvider
                       .select((value) => value.exchangeRateType)) ==
                   ExchangeRateType.estimated ||
@@ -1304,16 +1366,27 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
             ),
           ),
         ),
-        const SizedBox(
-          height: 12,
+        if (ref
+                .watch(
+                    exchangeFormStateProvider.select((value) => value.warning))
+                .isNotEmpty &&
+            ref.watch(
+                exchangeFormStateProvider.select((value) => value.reversed)))
+          Text(
+            ref.watch(
+                exchangeFormStateProvider.select((value) => value.warning)),
+            style: STextStyles.errorSmall(context),
+          ),
+        SizedBox(
+          height: isDesktop ? 20 : 12,
         ),
         RateTypeToggle(
           onChanged: onRateTypeChanged,
         ),
         if (ref.read(exchangeFormStateProvider).fromAmount != null &&
             ref.read(exchangeFormStateProvider).fromAmount != Decimal.zero)
-          const SizedBox(
-            height: 8,
+          SizedBox(
+            height: isDesktop ? 20 : 12,
           ),
         if (ref.read(exchangeFormStateProvider).fromAmount != null &&
             ref.read(exchangeFormStateProvider).fromAmount != Decimal.zero)
@@ -1328,10 +1401,11 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
             reversed: ref.watch(
                 exchangeFormStateProvider.select((value) => value.reversed)),
           ),
-        const SizedBox(
-          height: 12,
+        SizedBox(
+          height: isDesktop ? 20 : 12,
         ),
         PrimaryButton(
+          buttonHeight: isDesktop ? ButtonHeight.l : null,
           enabled: ref.watch(
               exchangeFormStateProvider.select((value) => value.canExchange)),
           onPressed: ref.watch(exchangeFormStateProvider

From 51cfc3f4dfce57fd22832173bdd0f2a3daddbdf0 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Fri, 18 Nov 2022 16:14:27 -0600
Subject: [PATCH 049/100] light colors accent blue fix?

---
 lib/utilities/theme/light_colors.dart | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/utilities/theme/light_colors.dart b/lib/utilities/theme/light_colors.dart
index ea3a7cb92..896ae4e5e 100644
--- a/lib/utilities/theme/light_colors.dart
+++ b/lib/utilities/theme/light_colors.dart
@@ -11,7 +11,7 @@ class LightColors extends StackColorTheme {
   Color get overlay => const Color(0xFF111215);
 
   @override
-  Color get accentColorBlue => const Color(0xFF4C86E9);
+  Color get accentColorBlue => const Color(0xFF0052DF);
   @override
   Color get accentColorGreen => const Color(0xFF4CC0A0);
   @override

From 80802727381722405be4bee6a06941b076d9510d Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Fri, 18 Nov 2022 16:19:38 -0700
Subject: [PATCH 050/100] WIP: delete wallet

---
 .../wallet_view/desktop_wallet_view.dart      |   5 +
 .../sub_widgets/delete_wallet_button.dart     | 238 ++++++++++++++++++
 2 files changed, 243 insertions(+)
 create mode 100644 lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
index 85dde4aba..739dbe1a1 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
@@ -8,6 +8,7 @@ import 'package:flutter_svg/svg.dart';
 import 'package:stackwallet/notifications/show_flush_bar.dart';
 import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
 import 'package:stackwallet/pages/exchange_view/wallet_initiated_exchange_view.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/my_wallet.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/network_info_button.dart';
@@ -412,6 +413,10 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
                   WalletKeysButton(
                     walletId: walletId,
                   ),
+                  const SizedBox(
+                    width: 2,
+                  ),
+                  DeleteWalletButton(),
                   const SizedBox(
                     width: 12,
                   ),
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
new file mode 100644
index 000000000..f45367d0b
--- /dev/null
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
@@ -0,0 +1,238 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/constants.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/stack_text_field.dart';
+
+class DeleteWalletButton extends ConsumerStatefulWidget {
+  const DeleteWalletButton({
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  ConsumerState<DeleteWalletButton> createState() => _DeleteWalletButton();
+}
+
+class _DeleteWalletButton extends ConsumerState<DeleteWalletButton> {
+  late final TextEditingController passwordController;
+  late final FocusNode passwordFocusNode;
+
+  bool hidePassword = true;
+  bool _continueEnabled = false;
+
+  Future<void> attentionDelete() async {
+    await showDialog<dynamic>(
+      context: context,
+      useSafeArea: false,
+      barrierDismissible: true,
+      builder: (context) => DesktopDialog(
+        maxWidth: 580,
+        maxHeight: 400,
+        child: Column(
+          children: [
+            Row(
+              mainAxisAlignment: MainAxisAlignment.end,
+              children: const [
+                DesktopDialogCloseButton(),
+              ],
+            ),
+            Column(
+              children: [
+                Padding(
+                  padding:
+                      const EdgeInsets.symmetric(horizontal: 32, vertical: 26),
+                  child: Text(
+                    "Attention!",
+                    style: STextStyles.desktopH2(context),
+                  ),
+                ),
+              ],
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  @override
+  void initState() {
+    passwordController = TextEditingController();
+    passwordFocusNode = FocusNode();
+
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    passwordController.dispose();
+    passwordFocusNode.dispose();
+
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return RawMaterialButton(
+      shape: RoundedRectangleBorder(
+        borderRadius: BorderRadius.circular(1000),
+      ),
+      onPressed: () {
+        showDialog(
+          barrierDismissible: true,
+          context: context,
+          builder: (context) => DesktopDialog(
+            maxHeight: 475,
+            child: Column(
+              children: [
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.end,
+                  children: const [
+                    DesktopDialogCloseButton(),
+                  ],
+                ),
+                Padding(
+                  padding:
+                      const EdgeInsets.symmetric(horizontal: 32, vertical: 26),
+                  child: Column(
+                    children: [
+                      const SizedBox(height: 16),
+                      Text(
+                        "Delete wallet",
+                        style: STextStyles.desktopH2(context),
+                      ),
+                      const SizedBox(height: 16),
+                      Text(
+                        "Enter your password",
+                        style: STextStyles.desktopTextMedium(context).copyWith(
+                          color: Theme.of(context)
+                              .extension<StackColors>()!
+                              .textDark3,
+                        ),
+                      ),
+                      const SizedBox(height: 24),
+                      ClipRRect(
+                        borderRadius: BorderRadius.circular(
+                          Constants.size.circularBorderRadius,
+                        ),
+                        child: TextField(
+                          key: const Key("desktopDeleteWalletPasswordFieldKey"),
+                          focusNode: passwordFocusNode,
+                          controller: passwordController,
+                          style: STextStyles.field(context),
+                          obscureText: hidePassword,
+                          enableSuggestions: false,
+                          autocorrect: false,
+                          decoration: standardInputDecoration(
+                            "Enter password",
+                            passwordFocusNode,
+                            context,
+                          ).copyWith(
+                            labelStyle: STextStyles.fieldLabel(context),
+                            suffixIcon: UnconstrainedBox(
+                              child: SizedBox(
+                                height: 70,
+                                child: Row(
+                                  children: [
+                                    const SizedBox(
+                                      width: 24,
+                                    ),
+                                    GestureDetector(
+                                      key: const Key(
+                                          "desktopDeleteWalletShowPasswordButtonKey"),
+                                      onTap: () async {
+                                        setState(() {
+                                          hidePassword = !hidePassword;
+                                        });
+                                      },
+                                      child: MouseRegion(
+                                        cursor: SystemMouseCursors.click,
+                                        child: SvgPicture.asset(
+                                          hidePassword
+                                              ? Assets.svg.eye
+                                              : Assets.svg.eyeSlash,
+                                          color: Theme.of(context)
+                                              .extension<StackColors>()!
+                                              .textDark3,
+                                          width: 24,
+                                          height: 24,
+                                        ),
+                                      ),
+                                    ),
+                                    const SizedBox(
+                                      width: 12,
+                                    ),
+                                  ],
+                                ),
+                              ),
+                            ),
+                          ),
+                          onChanged: (newValue) {
+                            setState(() {
+                              _continueEnabled =
+                                  passwordController.text.isNotEmpty;
+                            });
+                          },
+                        ),
+                      ),
+                      const SizedBox(height: 50),
+                      Row(
+                        mainAxisAlignment: MainAxisAlignment.center,
+                        children: [
+                          SecondaryButton(
+                            width: 250,
+                            buttonHeight: ButtonHeight.xl,
+                            label: "Cancel",
+                            onPressed: () {
+                              Navigator.of(context).pop();
+                            },
+                          ),
+                          const SizedBox(width: 16),
+                          PrimaryButton(
+                            width: 250,
+                            buttonHeight: ButtonHeight.xl,
+                            enabled: _continueEnabled,
+                            label: "Continue",
+                            onPressed: () {
+                              Navigator.of(context).pop();
+
+                              attentionDelete();
+                            },
+                          ),
+                        ],
+                      )
+                    ],
+                  ),
+                ),
+              ],
+            ),
+          ),
+        );
+      },
+      child: Padding(
+        padding: const EdgeInsets.symmetric(
+          vertical: 19,
+          horizontal: 32,
+        ),
+        child: Row(
+          children: [
+            SvgPicture.asset(
+              Assets.svg.ellipsis,
+              width: 20,
+              height: 20,
+              color: Theme.of(context)
+                  .extension<StackColors>()!
+                  .buttonTextSecondary,
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}

From 92da601fb80350706b412bc72bc2f952120446a0 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Fri, 18 Nov 2022 17:43:35 -0700
Subject: [PATCH 051/100] WIP: delete wallete Attention dialog

---
 .../sub_widgets/delete_wallet_button.dart     | 66 ++++++++++++++++---
 1 file changed, 56 insertions(+), 10 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
index f45367d0b..96930c044 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
@@ -9,6 +9,7 @@ import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/rounded_container.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 
 class DeleteWalletButton extends ConsumerStatefulWidget {
@@ -34,7 +35,7 @@ class _DeleteWalletButton extends ConsumerState<DeleteWalletButton> {
       barrierDismissible: true,
       builder: (context) => DesktopDialog(
         maxWidth: 580,
-        maxHeight: 400,
+        maxHeight: 530,
         child: Column(
           children: [
             Row(
@@ -43,17 +44,62 @@ class _DeleteWalletButton extends ConsumerState<DeleteWalletButton> {
                 DesktopDialogCloseButton(),
               ],
             ),
-            Column(
-              children: [
-                Padding(
-                  padding:
-                      const EdgeInsets.symmetric(horizontal: 32, vertical: 26),
-                  child: Text(
+            Padding(
+              padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 26),
+              child: Column(
+                children: [
+                  Text(
                     "Attention!",
                     style: STextStyles.desktopH2(context),
                   ),
-                ),
-              ],
+                  const SizedBox(
+                    height: 16,
+                  ),
+                  RoundedContainer(
+                    color: Theme.of(context)
+                        .extension<StackColors>()!
+                        .snackBarBackError,
+                    child: Padding(
+                      padding: const EdgeInsets.all(10.0),
+                      child: Text(
+                        "You are going to permanently delete you wallet.\n\nIf you delete your wallet, "
+                        "the only way you can have access to your funds is by using your backup key."
+                        "\n\nStack Wallet does not keep nor is able to restore your backup key or your wallet."
+                        "\n\nPLEASE SAVE YOUR BACKUP KEY.",
+                        style: STextStyles.desktopTextExtraExtraSmall(context)
+                            .copyWith(
+                          color: Theme.of(context)
+                              .extension<StackColors>()!
+                              .textDark3,
+                        ),
+                      ),
+                    ),
+                  ),
+                  const SizedBox(height: 30),
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    children: [
+                      SecondaryButton(
+                        width: 250,
+                        buttonHeight: ButtonHeight.xl,
+                        label: "Cancel",
+                        onPressed: () {
+                          Navigator.of(context).pop();
+                        },
+                      ),
+                      const SizedBox(width: 16),
+                      PrimaryButton(
+                        width: 250,
+                        buttonHeight: ButtonHeight.xl,
+                        label: "View Backup Key",
+                        onPressed: () {
+                          Navigator.of(context).pop();
+                        },
+                      ),
+                    ],
+                  )
+                ],
+              ),
             ),
           ],
         ),
@@ -84,7 +130,7 @@ class _DeleteWalletButton extends ConsumerState<DeleteWalletButton> {
         borderRadius: BorderRadius.circular(1000),
       ),
       onPressed: () {
-        showDialog(
+        showDialog<dynamic>(
           barrierDismissible: true,
           context: context,
           builder: (context) => DesktopDialog(

From 5f1a485ed5b4a7f2db44bee6a06172774fafe5a6 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Sat, 19 Nov 2022 11:00:15 -0700
Subject: [PATCH 052/100] WIP: delete wallete stateful widget + attention
 warning dialog

---
 .../wallet_view/desktop_wallet_view.dart      |   4 +-
 .../sub_widgets/delete_wallet_button.dart     | 253 ++-------------
 .../desktop_delete_wallet_dialog.dart         | 299 ++++++++++++++++++
 lib/route_generator.dart                      |  23 ++
 4 files changed, 350 insertions(+), 229 deletions(-)
 create mode 100644 lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
index 739dbe1a1..5996597b5 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart
@@ -416,7 +416,9 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
                   const SizedBox(
                     width: 2,
                   ),
-                  DeleteWalletButton(),
+                  DeleteWalletButton(
+                    walletId: walletId,
+                  ),
                   const SizedBox(
                     width: 12,
                   ),
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
index 96930c044..54f991c37 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
@@ -1,128 +1,37 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/svg.dart';
+import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/route_generator.dart';
 import 'package:stackwallet/utilities/assets.dart';
-import 'package:stackwallet/utilities/constants.dart';
-import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
-import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
-import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
-import 'package:stackwallet/widgets/desktop/primary_button.dart';
-import 'package:stackwallet/widgets/desktop/secondary_button.dart';
-import 'package:stackwallet/widgets/rounded_container.dart';
-import 'package:stackwallet/widgets/stack_text_field.dart';
+
+import 'desktop_delete_wallet_dialog.dart';
 
 class DeleteWalletButton extends ConsumerStatefulWidget {
   const DeleteWalletButton({
     Key? key,
+    required this.walletId,
   }) : super(key: key);
 
+  final String walletId;
+
   @override
   ConsumerState<DeleteWalletButton> createState() => _DeleteWalletButton();
 }
 
 class _DeleteWalletButton extends ConsumerState<DeleteWalletButton> {
-  late final TextEditingController passwordController;
-  late final FocusNode passwordFocusNode;
-
-  bool hidePassword = true;
-  bool _continueEnabled = false;
-
-  Future<void> attentionDelete() async {
-    await showDialog<dynamic>(
-      context: context,
-      useSafeArea: false,
-      barrierDismissible: true,
-      builder: (context) => DesktopDialog(
-        maxWidth: 580,
-        maxHeight: 530,
-        child: Column(
-          children: [
-            Row(
-              mainAxisAlignment: MainAxisAlignment.end,
-              children: const [
-                DesktopDialogCloseButton(),
-              ],
-            ),
-            Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 26),
-              child: Column(
-                children: [
-                  Text(
-                    "Attention!",
-                    style: STextStyles.desktopH2(context),
-                  ),
-                  const SizedBox(
-                    height: 16,
-                  ),
-                  RoundedContainer(
-                    color: Theme.of(context)
-                        .extension<StackColors>()!
-                        .snackBarBackError,
-                    child: Padding(
-                      padding: const EdgeInsets.all(10.0),
-                      child: Text(
-                        "You are going to permanently delete you wallet.\n\nIf you delete your wallet, "
-                        "the only way you can have access to your funds is by using your backup key."
-                        "\n\nStack Wallet does not keep nor is able to restore your backup key or your wallet."
-                        "\n\nPLEASE SAVE YOUR BACKUP KEY.",
-                        style: STextStyles.desktopTextExtraExtraSmall(context)
-                            .copyWith(
-                          color: Theme.of(context)
-                              .extension<StackColors>()!
-                              .textDark3,
-                        ),
-                      ),
-                    ),
-                  ),
-                  const SizedBox(height: 30),
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.center,
-                    children: [
-                      SecondaryButton(
-                        width: 250,
-                        buttonHeight: ButtonHeight.xl,
-                        label: "Cancel",
-                        onPressed: () {
-                          Navigator.of(context).pop();
-                        },
-                      ),
-                      const SizedBox(width: 16),
-                      PrimaryButton(
-                        width: 250,
-                        buttonHeight: ButtonHeight.xl,
-                        label: "View Backup Key",
-                        onPressed: () {
-                          Navigator.of(context).pop();
-                        },
-                      ),
-                    ],
-                  )
-                ],
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
+  late final String walletId;
 
   @override
   void initState() {
-    passwordController = TextEditingController();
-    passwordFocusNode = FocusNode();
+    walletId = widget.walletId;
+    final managerProvider =
+        ref.read(walletsChangeNotifierProvider).getManagerProvider(walletId);
 
     super.initState();
   }
 
-  @override
-  void dispose() {
-    passwordController.dispose();
-    passwordFocusNode.dispose();
-
-    super.dispose();
-  }
-
   @override
   Widget build(BuildContext context) {
     return RawMaterialButton(
@@ -130,134 +39,22 @@ class _DeleteWalletButton extends ConsumerState<DeleteWalletButton> {
         borderRadius: BorderRadius.circular(1000),
       ),
       onPressed: () {
-        showDialog<dynamic>(
-          barrierDismissible: true,
+        showDialog<void>(
           context: context,
-          builder: (context) => DesktopDialog(
-            maxHeight: 475,
-            child: Column(
-              children: [
-                Row(
-                  mainAxisAlignment: MainAxisAlignment.end,
-                  children: const [
-                    DesktopDialogCloseButton(),
-                  ],
-                ),
-                Padding(
-                  padding:
-                      const EdgeInsets.symmetric(horizontal: 32, vertical: 26),
-                  child: Column(
-                    children: [
-                      const SizedBox(height: 16),
-                      Text(
-                        "Delete wallet",
-                        style: STextStyles.desktopH2(context),
-                      ),
-                      const SizedBox(height: 16),
-                      Text(
-                        "Enter your password",
-                        style: STextStyles.desktopTextMedium(context).copyWith(
-                          color: Theme.of(context)
-                              .extension<StackColors>()!
-                              .textDark3,
-                        ),
-                      ),
-                      const SizedBox(height: 24),
-                      ClipRRect(
-                        borderRadius: BorderRadius.circular(
-                          Constants.size.circularBorderRadius,
-                        ),
-                        child: TextField(
-                          key: const Key("desktopDeleteWalletPasswordFieldKey"),
-                          focusNode: passwordFocusNode,
-                          controller: passwordController,
-                          style: STextStyles.field(context),
-                          obscureText: hidePassword,
-                          enableSuggestions: false,
-                          autocorrect: false,
-                          decoration: standardInputDecoration(
-                            "Enter password",
-                            passwordFocusNode,
-                            context,
-                          ).copyWith(
-                            labelStyle: STextStyles.fieldLabel(context),
-                            suffixIcon: UnconstrainedBox(
-                              child: SizedBox(
-                                height: 70,
-                                child: Row(
-                                  children: [
-                                    const SizedBox(
-                                      width: 24,
-                                    ),
-                                    GestureDetector(
-                                      key: const Key(
-                                          "desktopDeleteWalletShowPasswordButtonKey"),
-                                      onTap: () async {
-                                        setState(() {
-                                          hidePassword = !hidePassword;
-                                        });
-                                      },
-                                      child: MouseRegion(
-                                        cursor: SystemMouseCursors.click,
-                                        child: SvgPicture.asset(
-                                          hidePassword
-                                              ? Assets.svg.eye
-                                              : Assets.svg.eyeSlash,
-                                          color: Theme.of(context)
-                                              .extension<StackColors>()!
-                                              .textDark3,
-                                          width: 24,
-                                          height: 24,
-                                        ),
-                                      ),
-                                    ),
-                                    const SizedBox(
-                                      width: 12,
-                                    ),
-                                  ],
-                                ),
-                              ),
-                            ),
-                          ),
-                          onChanged: (newValue) {
-                            setState(() {
-                              _continueEnabled =
-                                  passwordController.text.isNotEmpty;
-                            });
-                          },
-                        ),
-                      ),
-                      const SizedBox(height: 50),
-                      Row(
-                        mainAxisAlignment: MainAxisAlignment.center,
-                        children: [
-                          SecondaryButton(
-                            width: 250,
-                            buttonHeight: ButtonHeight.xl,
-                            label: "Cancel",
-                            onPressed: () {
-                              Navigator.of(context).pop();
-                            },
-                          ),
-                          const SizedBox(width: 16),
-                          PrimaryButton(
-                            width: 250,
-                            buttonHeight: ButtonHeight.xl,
-                            enabled: _continueEnabled,
-                            label: "Continue",
-                            onPressed: () {
-                              Navigator.of(context).pop();
-
-                              attentionDelete();
-                            },
-                          ),
-                        ],
-                      )
-                    ],
+          barrierDismissible: false,
+          builder: (context) => Navigator(
+            initialRoute: DesktopDeleteWalletDialog.routeName,
+            onGenerateRoute: RouteGenerator.generateRoute,
+            onGenerateInitialRoutes: (_, __) {
+              return [
+                RouteGenerator.generateRoute(
+                  RouteSettings(
+                    name: DesktopDeleteWalletDialog.routeName,
+                    arguments: walletId,
                   ),
-                ),
-              ],
-            ),
+                )
+              ];
+            },
           ),
         );
       },
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
new file mode 100644
index 000000000..e2ab4fa86
--- /dev/null
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
@@ -0,0 +1,299 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:stackwallet/notifications/show_flush_bar.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/constants.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/rounded_container.dart';
+import 'package:stackwallet/widgets/stack_text_field.dart';
+
+import '../../../../../providers/desktop/storage_crypto_handler_provider.dart';
+import '../../../../../providers/global/wallets_provider.dart';
+
+class DesktopDeleteWalletDialog extends ConsumerStatefulWidget {
+  const DesktopDeleteWalletDialog({
+    Key? key,
+    required this.walletId,
+  }) : super(key: key);
+
+  final String walletId;
+
+  static const String routeName = "/desktopDeleteWalletDialog";
+
+  @override
+  ConsumerState<DesktopDeleteWalletDialog> createState() =>
+      _DesktopDeleteWalletDialog();
+}
+
+class _DesktopDeleteWalletDialog
+    extends ConsumerState<DesktopDeleteWalletDialog> {
+  late final TextEditingController passwordController;
+  late final FocusNode passwordFocusNode;
+
+  bool hidePassword = true;
+  bool _continueEnabled = false;
+
+  Future<void> attentionDelete() async {
+    await showDialog<dynamic>(
+      context: context,
+      useSafeArea: false,
+      barrierDismissible: true,
+      builder: (context) => DesktopDialog(
+        maxWidth: 610,
+        maxHeight: 530,
+        child: Column(
+          children: [
+            Row(
+              mainAxisAlignment: MainAxisAlignment.end,
+              children: [
+                DesktopDialogCloseButton(
+                  onPressedOverride: () {
+                    int count = 0;
+                    Navigator.of(context).popUntil((_) => count++ >= 2);
+                  },
+                ),
+              ],
+            ),
+            Padding(
+              padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 26),
+              child: Column(
+                children: [
+                  Text(
+                    "Attention!",
+                    style: STextStyles.desktopH2(context),
+                  ),
+                  const SizedBox(
+                    height: 16,
+                  ),
+                  RoundedContainer(
+                    color: Theme.of(context)
+                        .extension<StackColors>()!
+                        .snackBarBackError,
+                    child: Padding(
+                      padding: const EdgeInsets.all(10.0),
+                      child: Text(
+                        "You are going to permanently delete you wallet.\n\nIf you delete your wallet, "
+                        "the only way you can have access to your funds is by using your backup key."
+                        "\n\nStack Wallet does not keep nor is able to restore your backup key or your wallet."
+                        "\n\nPLEASE SAVE YOUR BACKUP KEY.",
+                        style: STextStyles.desktopTextExtraExtraSmall(context)
+                            .copyWith(
+                          color: Theme.of(context)
+                              .extension<StackColors>()!
+                              .textDark3,
+                        ),
+                      ),
+                    ),
+                  ),
+                  const SizedBox(height: 30),
+                  Row(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    children: [
+                      SecondaryButton(
+                        width: 250,
+                        buttonHeight: ButtonHeight.xl,
+                        label: "Cancel",
+                        onPressed: () {
+                          int count = 0;
+                          Navigator.of(context).popUntil((_) => count++ >= 2);
+                        },
+                      ),
+                      const SizedBox(width: 16),
+                      PrimaryButton(
+                        width: 250,
+                        buttonHeight: ButtonHeight.xl,
+                        label: "View Backup Key",
+                        onPressed: () {},
+                      ),
+                    ],
+                  )
+                ],
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  @override
+  void initState() {
+    passwordController = TextEditingController();
+    passwordFocusNode = FocusNode();
+
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    passwordController.dispose();
+    passwordFocusNode.dispose();
+
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return DesktopDialog(
+      maxWidth: 580,
+      maxHeight: double.infinity,
+      child: Column(
+        children: [
+          Row(
+            mainAxisAlignment: MainAxisAlignment.end,
+            children: [
+              DesktopDialogCloseButton(
+                onPressedOverride: Navigator.of(
+                  context,
+                  rootNavigator: true,
+                ).pop,
+              ),
+            ],
+          ),
+          Padding(
+            padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 26),
+            child: Column(
+              children: [
+                const SizedBox(height: 16),
+                Text(
+                  "Delete wallet",
+                  style: STextStyles.desktopH2(context),
+                ),
+                const SizedBox(height: 16),
+                Text(
+                  "Enter your password",
+                  style: STextStyles.desktopTextMedium(context).copyWith(
+                    color:
+                        Theme.of(context).extension<StackColors>()!.textDark3,
+                  ),
+                ),
+                const SizedBox(height: 24),
+                ClipRRect(
+                  borderRadius: BorderRadius.circular(
+                    Constants.size.circularBorderRadius,
+                  ),
+                  child: TextField(
+                    key: const Key("desktopDeleteWalletPasswordFieldKey"),
+                    focusNode: passwordFocusNode,
+                    controller: passwordController,
+                    style: STextStyles.field(context),
+                    obscureText: hidePassword,
+                    enableSuggestions: false,
+                    autocorrect: false,
+                    decoration: standardInputDecoration(
+                      "Enter password",
+                      passwordFocusNode,
+                      context,
+                    ).copyWith(
+                      labelStyle: STextStyles.fieldLabel(context),
+                      suffixIcon: UnconstrainedBox(
+                        child: SizedBox(
+                          height: 70,
+                          child: Row(
+                            children: [
+                              const SizedBox(
+                                width: 24,
+                              ),
+                              GestureDetector(
+                                key: const Key(
+                                    "desktopDeleteWalletShowPasswordButtonKey"),
+                                onTap: () async {
+                                  setState(() {
+                                    hidePassword = !hidePassword;
+                                  });
+                                },
+                                child: MouseRegion(
+                                  cursor: SystemMouseCursors.click,
+                                  child: SvgPicture.asset(
+                                    hidePassword
+                                        ? Assets.svg.eye
+                                        : Assets.svg.eyeSlash,
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textDark3,
+                                    width: 24,
+                                    height: 24,
+                                  ),
+                                ),
+                              ),
+                              const SizedBox(
+                                width: 12,
+                              ),
+                            ],
+                          ),
+                        ),
+                      ),
+                    ),
+                    onChanged: (newValue) {
+                      setState(() {
+                        _continueEnabled = passwordController.text.isNotEmpty;
+                      });
+                    },
+                  ),
+                ),
+                const SizedBox(height: 50),
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.center,
+                  children: [
+                    SecondaryButton(
+                      width: 250,
+                      buttonHeight: ButtonHeight.xl,
+                      label: "Cancel",
+                      onPressed: Navigator.of(
+                        context,
+                        rootNavigator: true,
+                      ).pop,
+                    ),
+                    const SizedBox(width: 16),
+                    PrimaryButton(
+                      width: 250,
+                      buttonHeight: ButtonHeight.xl,
+                      enabled: _continueEnabled,
+                      label: "Continue",
+                      onPressed: _continueEnabled
+                          ? () async {
+                              final verified = await ref
+                                  .read(storageCryptoHandlerProvider)
+                                  .verifyPassphrase(passwordController.text);
+
+                              if (verified) {
+                                final words = await ref
+                                    .read(walletsChangeNotifierProvider)
+                                    .getManager(widget.walletId)
+                                    .mnemonic;
+
+                                if (mounted) {
+                                  Navigator.of(context).pop();
+
+                                  attentionDelete();
+                                }
+                              } else {
+                                unawaited(
+                                  showFloatingFlushBar(
+                                    type: FlushBarType.warning,
+                                    message: "Invalid passphrase!",
+                                    context: context,
+                                  ),
+                                );
+                              }
+                            }
+                          : null,
+                    ),
+                  ],
+                )
+              ],
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/route_generator.dart b/lib/route_generator.dart
index 8ccc923bc..77b5e7d11 100644
--- a/lib/route_generator.dart
+++ b/lib/route_generator.dart
@@ -92,6 +92,7 @@ import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/desktop_settings_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_stack_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/qr_code_desktop_popup_content.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart';
 import 'package:stackwallet/pages_desktop_specific/home/notifications/desktop_notifications_view.dart';
@@ -1170,6 +1171,28 @@ class RouteGenerator {
         }
         return _routeError("${settings.name} invalid args: ${args.toString()}");
 
+      case DesktopDeleteWalletDialog.routeName:
+        if (args is String) {
+          return FadePageRoute(
+            DesktopDeleteWalletDialog(
+              walletId: args,
+            ),
+            RouteSettings(
+              name: settings.name,
+            ),
+          );
+          // return getRoute(
+          //   shouldUseMaterialRoute: useMaterialPageRoute,
+          //   builder: (_) => WalletKeysDesktopPopup(
+          //     words: args,
+          //   ),
+          //   settings: RouteSettings(
+          //     name: settings.name,
+          //   ),
+          // );
+        }
+        return _routeError("${settings.name} invalid args: ${args.toString()}");
+
       case QRCodeDesktopPopupContent.routeName:
         if (args is String) {
           return FadePageRoute(

From a8faa7b8e7b851c0e919b0678f9d066fc237120a Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 19 Nov 2022 09:20:43 -0600
Subject: [PATCH 053/100] exchange form desktop routing and dialogs

---
 lib/pages/exchange_view/exchange_form.dart    | 223 +++++++++++++-----
 .../desktop/simple_desktop_dialog.dart        |  65 +++++
 2 files changed, 229 insertions(+), 59 deletions(-)
 create mode 100644 lib/widgets/desktop/simple_desktop_dialog.dart

diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart
index 5ece5aba8..a6d736228 100644
--- a/lib/pages/exchange_view/exchange_form.dart
+++ b/lib/pages/exchange_view/exchange_form.dart
@@ -30,7 +30,11 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/utilities/util.dart';
 import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/custom_loading_overlay.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/desktop/simple_desktop_dialog.dart';
 import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/rounded_container.dart';
 import 'package:stackwallet/widgets/stack_dialog.dart';
@@ -139,14 +143,27 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
                     .read(exchangeFormStateProvider)
                     .updateMarket(market, true);
               } catch (e) {
-                unawaited(showDialog<dynamic>(
-                  context: context,
-                  builder: (_) => const StackDialog(
-                    title: "Fixed rate market error",
-                    message:
-                        "Could not find the specified fixed rate trade pair",
+                unawaited(
+                  showDialog<dynamic>(
+                    context: context,
+                    builder: (_) {
+                      if (isDesktop) {
+                        return const SimpleDesktopDialog(
+                          title: "Fixed rate market error",
+                          message:
+                              "Could not find the specified fixed rate trade pair",
+                        );
+                      } else {
+                        return const StackDialog(
+                          title: "Fixed rate market error",
+                          message:
+                              "Could not find the specified fixed rate trade pair",
+                        );
+                      }
+                    },
                   ),
-                ));
+                );
+
                 return;
               }
             },
@@ -229,14 +246,26 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
                     .read(exchangeFormStateProvider)
                     .updateMarket(market, true);
               } catch (e) {
-                unawaited(showDialog<dynamic>(
-                  context: context,
-                  builder: (_) => const StackDialog(
-                    title: "Fixed rate market error",
-                    message:
-                        "Could not find the specified fixed rate trade pair",
+                unawaited(
+                  showDialog<dynamic>(
+                    context: context,
+                    builder: (_) {
+                      if (isDesktop) {
+                        return const SimpleDesktopDialog(
+                          title: "Fixed rate market error",
+                          message:
+                              "Could not find the specified fixed rate trade pair",
+                        );
+                      } else {
+                        return const StackDialog(
+                          title: "Fixed rate market error",
+                          message:
+                              "Could not find the specified fixed rate trade pair",
+                        );
+                      }
+                    },
                   ),
-                ));
+                );
                 return;
               }
             },
@@ -324,7 +353,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
       await ref.read(exchangeFormStateProvider).swap();
     }
     if (mounted) {
-      Navigator.of(context).pop();
+      Navigator.of(context, rootNavigator: isDesktop).pop();
     }
     _swapLock = false;
   }
@@ -567,14 +596,14 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
                       ? "-"
                       : ref.read(exchangeFormStateProvider).toAmountString;
               if (mounted) {
-                Navigator.of(context).pop();
+                Navigator.of(context, rootNavigator: isDesktop).pop();
               }
               return;
             }
           }
         }
         if (mounted) {
-          Navigator.of(context).pop();
+          Navigator.of(context, rootNavigator: isDesktop).pop();
         }
         if (!(fromTicker == "-" || toTicker == "-")) {
           unawaited(
@@ -620,7 +649,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
                     true,
                   );
               if (mounted) {
-                Navigator.of(context).pop();
+                Navigator.of(context, rootNavigator: isDesktop).pop();
               }
               return;
             case SimpleSwapExchange.exchangeName:
@@ -657,7 +686,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
                           ? "-"
                           : ref.read(exchangeFormStateProvider).toAmountString;
                   if (mounted) {
-                    Navigator.of(context).pop();
+                    Navigator.of(context, rootNavigator: isDesktop).pop();
                   }
                   return;
                 }
@@ -669,7 +698,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
           }
         }
         if (mounted) {
-          Navigator.of(context).pop();
+          Navigator.of(context, rootNavigator: isDesktop).pop();
         }
         unawaited(
           showFloatingFlushBar(
@@ -722,15 +751,27 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
         }
 
         if (!isAvailable) {
-          unawaited(showDialog<dynamic>(
-            context: context,
-            barrierDismissible: true,
-            builder: (_) => StackDialog(
-              title: "Selected trade pair unavailable",
-              message:
-                  "The $fromTicker - $toTicker market is currently disabled for estimated/floating rate trades",
+          unawaited(
+            showDialog<dynamic>(
+              context: context,
+              barrierDismissible: true,
+              builder: (_) {
+                if (isDesktop) {
+                  return SimpleDesktopDialog(
+                    title: "Selected trade pair unavailable",
+                    message:
+                        "The $fromTicker - $toTicker market is currently disabled for estimated/floating rate trades",
+                  );
+                } else {
+                  return StackDialog(
+                    title: "Selected trade pair unavailable",
+                    message:
+                        "The $fromTicker - $toTicker market is currently disabled for estimated/floating rate trades",
+                  );
+                }
+              },
             ),
-          ));
+          );
           return;
         }
         rate =
@@ -744,37 +785,101 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
           shouldCancel = await showDialog<bool?>(
             context: context,
             barrierDismissible: true,
-            builder: (_) => StackDialog(
-              title: "Failed to update trade estimate",
-              message:
-                  "${estimate.warningMessage!}\n\nDo you want to attempt trade anyways?",
-              leftButton: TextButton(
-                style: Theme.of(context)
-                    .extension<StackColors>()!
-                    .getSecondaryEnabledButtonColor(context),
-                child: Text(
-                  "Cancel",
-                  style: STextStyles.itemSubtitle12(context),
-                ),
-                onPressed: () {
-                  // notify return to cancel
-                  Navigator.of(context).pop(true);
-                },
-              ),
-              rightButton: TextButton(
-                style: Theme.of(context)
-                    .extension<StackColors>()!
-                    .getPrimaryEnabledButtonColor(context),
-                child: Text(
-                  "Attempt",
-                  style: STextStyles.button(context),
-                ),
-                onPressed: () {
-                  // continue and try to attempt trade
-                  Navigator.of(context).pop(false);
-                },
-              ),
-            ),
+            builder: (_) {
+              if (isDesktop) {
+                return DesktopDialog(
+                  maxWidth: 500,
+                  maxHeight: 300,
+                  child: Column(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: [
+                      Row(
+                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                        children: [
+                          Text(
+                            "Failed to update trade estimate",
+                            style: STextStyles.desktopH3(context),
+                          ),
+                          const DesktopDialogCloseButton(),
+                        ],
+                      ),
+                      const Spacer(),
+                      Text(
+                        estimate.warningMessage!,
+                        style: STextStyles.desktopTextSmall(context),
+                      ),
+                      const Spacer(),
+                      Text(
+                        "Do you want to attempt trade anyways?",
+                        style: STextStyles.desktopTextSmall(context),
+                      ),
+                      const Spacer(
+                        flex: 2,
+                      ),
+                      Row(
+                        children: [
+                          Expanded(
+                            child: SecondaryButton(
+                              label: "Cancel",
+                              buttonHeight: ButtonHeight.l,
+                              onPressed: () => Navigator.of(
+                                context,
+                                rootNavigator: true,
+                              ).pop(true),
+                            ),
+                          ),
+                          const SizedBox(
+                            width: 16,
+                          ),
+                          Expanded(
+                            child: PrimaryButton(
+                              label: "Attempt",
+                              buttonHeight: ButtonHeight.l,
+                              onPressed: () => Navigator.of(
+                                context,
+                                rootNavigator: true,
+                              ).pop(false),
+                            ),
+                          ),
+                        ],
+                      )
+                    ],
+                  ),
+                );
+              } else {
+                return StackDialog(
+                  title: "Failed to update trade estimate",
+                  message:
+                      "${estimate.warningMessage!}\n\nDo you want to attempt trade anyways?",
+                  leftButton: TextButton(
+                    style: Theme.of(context)
+                        .extension<StackColors>()!
+                        .getSecondaryEnabledButtonColor(context),
+                    child: Text(
+                      "Cancel",
+                      style: STextStyles.itemSubtitle12(context),
+                    ),
+                    onPressed: () {
+                      // notify return to cancel
+                      Navigator.of(context).pop(true);
+                    },
+                  ),
+                  rightButton: TextButton(
+                    style: Theme.of(context)
+                        .extension<StackColors>()!
+                        .getPrimaryEnabledButtonColor(context),
+                    child: Text(
+                      "Attempt",
+                      style: STextStyles.button(context),
+                    ),
+                    onPressed: () {
+                      // continue and try to attempt trade
+                      Navigator.of(context).pop(false);
+                    },
+                  ),
+                );
+              }
+            },
           );
         }
 
diff --git a/lib/widgets/desktop/simple_desktop_dialog.dart b/lib/widgets/desktop/simple_desktop_dialog.dart
new file mode 100644
index 000000000..cd066c221
--- /dev/null
+++ b/lib/widgets/desktop/simple_desktop_dialog.dart
@@ -0,0 +1,65 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+
+class SimpleDesktopDialog extends StatelessWidget {
+  const SimpleDesktopDialog({
+    Key? key,
+    required this.title,
+    required this.message,
+  }) : super(key: key);
+
+  final String title;
+  final String message;
+
+  @override
+  Widget build(BuildContext context) {
+    return DesktopDialog(
+      maxWidth: 500,
+      maxHeight: 300,
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: [
+              Text(
+                title,
+                style: STextStyles.desktopH3(context),
+              ),
+              const DesktopDialogCloseButton(),
+            ],
+          ),
+          const Spacer(),
+          Text(
+            message,
+            style: STextStyles.desktopTextSmall(context),
+          ),
+          const Spacer(
+            flex: 2,
+          ),
+          Row(
+            children: [
+              const Spacer(),
+              const SizedBox(
+                width: 16,
+              ),
+              Expanded(
+                child: PrimaryButton(
+                  label: "Ok",
+                  buttonHeight: ButtonHeight.l,
+                  onPressed: Navigator.of(
+                    context,
+                    rootNavigator: true,
+                  ).pop,
+                ),
+              ),
+            ],
+          )
+        ],
+      ),
+    );
+  }
+}

From b2ff99be19400374c71b9e2fbe6be4eb08bc8147 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 19 Nov 2022 09:20:58 -0600
Subject: [PATCH 054/100] login loading indicator size

---
 lib/pages_desktop_specific/desktop_login_view.dart | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/lib/pages_desktop_specific/desktop_login_view.dart b/lib/pages_desktop_specific/desktop_login_view.dart
index f60ce2240..f865fad47 100644
--- a/lib/pages_desktop_specific/desktop_login_view.dart
+++ b/lib/pages_desktop_specific/desktop_login_view.dart
@@ -49,8 +49,15 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
       unawaited(
         showDialog(
           context: context,
-          builder: (context) => const LoadingIndicator(
-            width: 200,
+          builder: (context) => Column(
+            mainAxisAlignment: MainAxisAlignment.center,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: const [
+              LoadingIndicator(
+                width: 200,
+                height: 200,
+              ),
+            ],
           ),
         ),
       );

From cc4dc9e3c71d67745fd0294e38dd74ddd709f413 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 19 Nov 2022 09:24:32 -0600
Subject: [PATCH 055/100] exchange rate type toggle mouse regions

---
 .../sub_widgets/rate_type_toggle.dart         | 287 ++++++++++--------
 1 file changed, 153 insertions(+), 134 deletions(-)

diff --git a/lib/pages/exchange_view/sub_widgets/rate_type_toggle.dart b/lib/pages/exchange_view/sub_widgets/rate_type_toggle.dart
index 9697710e8..31ee01ce2 100644
--- a/lib/pages/exchange_view/sub_widgets/rate_type_toggle.dart
+++ b/lib/pages/exchange_view/sub_widgets/rate_type_toggle.dart
@@ -8,6 +8,7 @@ import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/rounded_container.dart';
 
 class RateTypeToggle extends ConsumerWidget {
@@ -35,145 +36,163 @@ class RateTypeToggle extends ConsumerWidget {
       child: Row(
         children: [
           Expanded(
-            child: GestureDetector(
-              onTap: () {
-                if (!estimated) {
-                  ref.read(prefsChangeNotifierProvider).exchangeRateType =
-                      ExchangeRateType.estimated;
-                  onChanged?.call(ExchangeRateType.estimated);
-                }
-              },
-              child: RoundedContainer(
-                padding: isDesktop
-                    ? const EdgeInsets.all(17)
-                    : const EdgeInsets.all(0),
-                color: estimated
-                    ? Theme.of(context)
-                        .extension<StackColors>()!
-                        .textFieldDefaultBG
-                    : Colors.transparent,
-                child: Row(
-                  mainAxisAlignment: MainAxisAlignment.center,
-                  children: [
-                    SvgPicture.asset(
-                      Assets.svg.lockOpen,
-                      width: 12,
-                      height: 14,
-                      color: isDesktop
-                          ? estimated
-                              ? Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .accentColorBlue
-                              : Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .buttonTextSecondary
-                          : estimated
-                              ? Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .textDark
-                              : Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .textSubtitle1,
-                    ),
-                    const SizedBox(
-                      width: 5,
-                    ),
-                    Text(
-                      "Estimate rate",
-                      style: isDesktop
-                          ? STextStyles.desktopTextExtraExtraSmall(context)
-                              .copyWith(
-                              color: estimated
-                                  ? Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .accentColorBlue
-                                  : Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .buttonTextSecondary,
-                            )
-                          : STextStyles.smallMed12(context).copyWith(
-                              color: estimated
-                                  ? Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textDark
-                                  : Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textSubtitle1,
-                            ),
-                    ),
-                  ],
+            child: ConditionalParent(
+              condition: isDesktop,
+              builder: (child) => MouseRegion(
+                cursor: estimated
+                    ? SystemMouseCursors.basic
+                    : SystemMouseCursors.click,
+                child: child,
+              ),
+              child: GestureDetector(
+                onTap: () {
+                  if (!estimated) {
+                    ref.read(prefsChangeNotifierProvider).exchangeRateType =
+                        ExchangeRateType.estimated;
+                    onChanged?.call(ExchangeRateType.estimated);
+                  }
+                },
+                child: RoundedContainer(
+                  padding: isDesktop
+                      ? const EdgeInsets.all(17)
+                      : const EdgeInsets.all(0),
+                  color: estimated
+                      ? Theme.of(context)
+                          .extension<StackColors>()!
+                          .textFieldDefaultBG
+                      : Colors.transparent,
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    children: [
+                      SvgPicture.asset(
+                        Assets.svg.lockOpen,
+                        width: 12,
+                        height: 14,
+                        color: isDesktop
+                            ? estimated
+                                ? Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .accentColorBlue
+                                : Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .buttonTextSecondary
+                            : estimated
+                                ? Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textDark
+                                : Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textSubtitle1,
+                      ),
+                      const SizedBox(
+                        width: 5,
+                      ),
+                      Text(
+                        "Estimate rate",
+                        style: isDesktop
+                            ? STextStyles.desktopTextExtraExtraSmall(context)
+                                .copyWith(
+                                color: estimated
+                                    ? Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .accentColorBlue
+                                    : Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .buttonTextSecondary,
+                              )
+                            : STextStyles.smallMed12(context).copyWith(
+                                color: estimated
+                                    ? Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textDark
+                                    : Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textSubtitle1,
+                              ),
+                      ),
+                    ],
+                  ),
                 ),
               ),
             ),
           ),
           Expanded(
-            child: GestureDetector(
-              onTap: () {
-                if (estimated) {
-                  ref.read(prefsChangeNotifierProvider).exchangeRateType =
-                      ExchangeRateType.fixed;
-                  onChanged?.call(ExchangeRateType.fixed);
-                }
-              },
-              child: RoundedContainer(
-                padding: isDesktop
-                    ? const EdgeInsets.all(17)
-                    : const EdgeInsets.all(0),
-                color: !estimated
-                    ? Theme.of(context)
-                        .extension<StackColors>()!
-                        .textFieldDefaultBG
-                    : Colors.transparent,
-                child: Row(
-                  mainAxisAlignment: MainAxisAlignment.center,
-                  children: [
-                    SvgPicture.asset(
-                      Assets.svg.lock,
-                      width: 12,
-                      height: 14,
-                      color: isDesktop
-                          ? !estimated
-                              ? Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .accentColorBlue
-                              : Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .buttonTextSecondary
-                          : !estimated
-                              ? Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .textDark
-                              : Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .textSubtitle1,
-                    ),
-                    const SizedBox(
-                      width: 5,
-                    ),
-                    Text(
-                      "Fixed rate",
-                      style: isDesktop
-                          ? STextStyles.desktopTextExtraExtraSmall(context)
-                              .copyWith(
-                              color: !estimated
-                                  ? Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .accentColorBlue
-                                  : Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .buttonTextSecondary,
-                            )
-                          : STextStyles.smallMed12(context).copyWith(
-                              color: !estimated
-                                  ? Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textDark
-                                  : Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textSubtitle1,
-                            ),
-                    ),
-                  ],
+            child: ConditionalParent(
+              condition: isDesktop,
+              builder: (child) => MouseRegion(
+                cursor: !estimated
+                    ? SystemMouseCursors.basic
+                    : SystemMouseCursors.click,
+                child: child,
+              ),
+              child: GestureDetector(
+                onTap: () {
+                  if (estimated) {
+                    ref.read(prefsChangeNotifierProvider).exchangeRateType =
+                        ExchangeRateType.fixed;
+                    onChanged?.call(ExchangeRateType.fixed);
+                  }
+                },
+                child: RoundedContainer(
+                  padding: isDesktop
+                      ? const EdgeInsets.all(17)
+                      : const EdgeInsets.all(0),
+                  color: !estimated
+                      ? Theme.of(context)
+                          .extension<StackColors>()!
+                          .textFieldDefaultBG
+                      : Colors.transparent,
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    children: [
+                      SvgPicture.asset(
+                        Assets.svg.lock,
+                        width: 12,
+                        height: 14,
+                        color: isDesktop
+                            ? !estimated
+                                ? Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .accentColorBlue
+                                : Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .buttonTextSecondary
+                            : !estimated
+                                ? Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textDark
+                                : Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textSubtitle1,
+                      ),
+                      const SizedBox(
+                        width: 5,
+                      ),
+                      Text(
+                        "Fixed rate",
+                        style: isDesktop
+                            ? STextStyles.desktopTextExtraExtraSmall(context)
+                                .copyWith(
+                                color: !estimated
+                                    ? Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .accentColorBlue
+                                    : Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .buttonTextSecondary,
+                              )
+                            : STextStyles.smallMed12(context).copyWith(
+                                color: !estimated
+                                    ? Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textDark
+                                    : Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textSubtitle1,
+                              ),
+                      ),
+                    ],
+                  ),
                 ),
               ),
             ),

From 601001f96df83e182959782e1de05e90e782ce9a Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 19 Nov 2022 10:01:09 -0600
Subject: [PATCH 056/100] WIP: desktop exchange steps flow ui

---
 lib/pages/exchange_view/exchange_form.dart    |  54 ++++++--
 .../exchange_steps/step_scaffold.dart         |  55 ++++++++
 .../desktop_exchange_steps_indicator.dart     | 121 ++++++++++++++++++
 3 files changed, 218 insertions(+), 12 deletions(-)
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart

diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart
index a6d736228..2d89c7660 100644
--- a/lib/pages/exchange_view/exchange_form.dart
+++ b/lib/pages/exchange_view/exchange_form.dart
@@ -18,6 +18,7 @@ import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_2_view.
 import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_provider_options.dart';
 import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
 import 'package:stackwallet/pages/exchange_view/sub_widgets/rate_type_toggle.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart';
 import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
 import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart';
@@ -908,20 +909,49 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
       if (walletInitiated) {
         ref.read(exchangeSendFromWalletIdStateProvider.state).state =
             Tuple2(walletId!, coin!);
-        unawaited(
-          Navigator.of(context).pushNamed(
-            Step2View.routeName,
-            arguments: model,
-          ),
-        );
+        if (isDesktop) {
+          await showDialog<void>(
+            context: context,
+            builder: (context) {
+              return const DesktopDialog(
+                maxWidth: 700,
+                child: StepScaffold(
+                  step: 1,
+                ),
+              );
+            },
+          );
+        } else {
+          unawaited(
+            Navigator.of(context).pushNamed(
+              Step2View.routeName,
+              arguments: model,
+            ),
+          );
+        }
       } else {
         ref.read(exchangeSendFromWalletIdStateProvider.state).state = null;
-        unawaited(
-          Navigator.of(context).pushNamed(
-            Step1View.routeName,
-            arguments: model,
-          ),
-        );
+
+        if (isDesktop) {
+          await showDialog<void>(
+            context: context,
+            builder: (context) {
+              return const DesktopDialog(
+                maxWidth: 700,
+                child: StepScaffold(
+                  step: 0,
+                ),
+              );
+            },
+          );
+        } else {
+          unawaited(
+            Navigator.of(context).pushNamed(
+              Step1View.routeName,
+              arguments: model,
+            ),
+          );
+        }
       }
     }
   }
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart
new file mode 100644
index 000000000..09aea9dbf
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart
@@ -0,0 +1,55 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+
+class StepScaffold extends StatefulWidget {
+  const StepScaffold({Key? key, required this.step}) : super(key: key);
+
+  final int step;
+
+  @override
+  State<StepScaffold> createState() => _StepScaffoldState();
+}
+
+class _StepScaffoldState extends State<StepScaffold> {
+  int currentStep = 0;
+
+  @override
+  void initState() {
+    currentStep = widget.step;
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        Row(
+          children: [
+            const AppBarBackButton(
+              isCompact: true,
+            ),
+            Text(
+              "Exchange XXX to XXX",
+              style: STextStyles.desktopH3(context),
+            ),
+          ],
+        ),
+        const SizedBox(
+          height: 32,
+        ),
+        DesktopExchangeStepsIndicator(
+          currentStep: currentStep,
+        ),
+        const SizedBox(
+          height: 32,
+        ),
+        Container(
+          height: 200,
+          color: Colors.red,
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart
new file mode 100644
index 000000000..44831bb4b
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart
@@ -0,0 +1,121 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/rounded_container.dart';
+
+class DesktopExchangeStepsIndicator extends StatelessWidget {
+  const DesktopExchangeStepsIndicator({Key? key, required this.currentStep})
+      : super(key: key);
+
+  final int currentStep;
+
+  Color getColor(BuildContext context, int step) {
+    if (currentStep > step) {
+      return Theme.of(context)
+          .extension<StackColors>()!
+          .accentColorBlue
+          .withOpacity(0.5);
+    } else if (currentStep < step) {
+      return Theme.of(context).extension<StackColors>()!.textSubtitle3;
+    } else {
+      return Theme.of(context).extension<StackColors>()!.accentColorBlue;
+    }
+  }
+
+  static const double verticalSpacing = 4;
+  static const double horizontalSpacing = 16;
+  static const double barHeight = 6;
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      children: [
+        Expanded(
+          child: Column(
+            children: [
+              Text(
+                "Confirm amount",
+                style: STextStyles.desktopTextSmall(context).copyWith(
+                  color: getColor(context, 0),
+                ),
+              ),
+              const SizedBox(
+                height: verticalSpacing,
+              ),
+              RoundedContainer(
+                color: getColor(context, 0),
+                height: barHeight,
+              ),
+            ],
+          ),
+        ),
+        const SizedBox(
+          width: horizontalSpacing,
+        ),
+        Expanded(
+          child: Column(
+            children: [
+              Text(
+                "Enter details",
+                style: STextStyles.desktopTextSmall(context).copyWith(
+                  color: getColor(context, 1),
+                ),
+              ),
+              const SizedBox(
+                height: verticalSpacing,
+              ),
+              RoundedContainer(
+                color: getColor(context, 1),
+                height: barHeight,
+              ),
+            ],
+          ),
+        ),
+        const SizedBox(
+          width: horizontalSpacing,
+        ),
+        Expanded(
+          child: Column(
+            children: [
+              Text(
+                "Confirm details",
+                style: STextStyles.desktopTextSmall(context).copyWith(
+                  color: getColor(context, 2),
+                ),
+              ),
+              const SizedBox(
+                height: verticalSpacing,
+              ),
+              RoundedContainer(
+                color: getColor(context, 2),
+                height: barHeight,
+              ),
+            ],
+          ),
+        ),
+        const SizedBox(
+          width: horizontalSpacing,
+        ),
+        Expanded(
+          child: Column(
+            children: [
+              Text(
+                "Complete exchange",
+                style: STextStyles.desktopTextSmall(context).copyWith(
+                  color: getColor(context, 3),
+                ),
+              ),
+              const SizedBox(
+                height: verticalSpacing,
+              ),
+              RoundedContainer(
+                color: getColor(context, 3),
+                height: barHeight,
+              ),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+}

From 90dc9e3116747ca80f0aa541bfce550bbee1113c Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 19 Nov 2022 11:32:18 -0600
Subject: [PATCH 057/100] mobile button height fix

---
 .../manage_nodes_views/node_details_view.dart                   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart
index 3d49ae6f7..71d764135 100644
--- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart
+++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart
@@ -349,7 +349,7 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
                 Expanded(
                   child: SecondaryButton(
                     label: "Test connection",
-                    buttonHeight: ButtonHeight.l,
+                    buttonHeight: isDesktop ? ButtonHeight.l : null,
                     onPressed: () async {
                       await _testConnection(ref, context);
                     },

From d4d85259e1c89d6f418c044a48e432704c83501b Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 19 Nov 2022 12:52:32 -0600
Subject: [PATCH 058/100] logging fix

---
 lib/services/coins/wownero/wownero_wallet.dart | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/services/coins/wownero/wownero_wallet.dart b/lib/services/coins/wownero/wownero_wallet.dart
index e39d13005..3d5ae3ad6 100644
--- a/lib/services/coins/wownero/wownero_wallet.dart
+++ b/lib/services/coins/wownero/wownero_wallet.dart
@@ -863,7 +863,8 @@ class WowneroWallet extends CoinServiceAPI {
         await DB.instance.get<dynamic>(boxName: walletId, key: indexKey) as int;
     // Use new index to derive a new receiving address
     final newReceivingAddress = await _generateAddressForChain(0, curIndex);
-    Logging.instance.log("xmr address in init existing: $newReceivingAddress",
+    Logging.instance.log(
+        "wownero address in init existing: $newReceivingAddress",
         level: LogLevel.Info);
     _currentReceivingAddress = Future(() => newReceivingAddress);
   }

From 719c7abd49906cc621612aabd19e4e1fe1776f43 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 19 Nov 2022 13:44:36 -0600
Subject: [PATCH 059/100] clean up logs

---
 lib/services/coins/monero/monero_wallet.dart   |  4 ++--
 lib/services/coins/wownero/wownero_wallet.dart | 12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/lib/services/coins/monero/monero_wallet.dart b/lib/services/coins/monero/monero_wallet.dart
index c35323d53..f94f0cd2a 100644
--- a/lib/services/coins/monero/monero_wallet.dart
+++ b/lib/services/coins/monero/monero_wallet.dart
@@ -185,8 +185,8 @@ class MoneroWallet extends CoinServiceAPI {
     try {
       if (walletBase!.syncStatus! is SyncedSyncStatus &&
           walletBase!.syncStatus!.progress() == 1.0) {
-        Logging.instance
-            .log("currentSyncingHeight lol", level: LogLevel.Warning);
+        // Logging.instance
+        //     .log("currentSyncingHeight lol", level: LogLevel.Warning);
         return getSyncingHeight();
       }
     } catch (e, s) {}
diff --git a/lib/services/coins/wownero/wownero_wallet.dart b/lib/services/coins/wownero/wownero_wallet.dart
index 3d5ae3ad6..e6a531b78 100644
--- a/lib/services/coins/wownero/wownero_wallet.dart
+++ b/lib/services/coins/wownero/wownero_wallet.dart
@@ -153,7 +153,7 @@ class WowneroWallet extends CoinServiceAPI {
     try {
       _height = (walletBase!.syncStatus as SyncingSyncStatus).height;
     } catch (e, s) {
-      Logging.instance.log("$e $s", level: LogLevel.Warning);
+      // Logging.instance.log("$e $s", level: LogLevel.Warning);
     }
 
     int blocksRemaining = -1;
@@ -162,7 +162,7 @@ class WowneroWallet extends CoinServiceAPI {
       blocksRemaining =
           (walletBase!.syncStatus as SyncingSyncStatus).blocksLeft;
     } catch (e, s) {
-      Logging.instance.log("$e $s", level: LogLevel.Warning);
+      // Logging.instance.log("$e $s", level: LogLevel.Warning);
     }
     int currentHeight = _height + blocksRemaining;
     if (_height == -1 || blocksRemaining == -1) {
@@ -186,8 +186,8 @@ class WowneroWallet extends CoinServiceAPI {
     try {
       if (walletBase!.syncStatus! is SyncedSyncStatus &&
           walletBase!.syncStatus!.progress() == 1.0) {
-        Logging.instance
-            .log("currentSyncingHeight lol", level: LogLevel.Warning);
+        // Logging.instance
+        //     .log("currentSyncingHeight lol", level: LogLevel.Warning);
         return getSyncingHeight();
       }
     } catch (e, s) {}
@@ -195,7 +195,7 @@ class WowneroWallet extends CoinServiceAPI {
     try {
       syncingHeight = (walletBase!.syncStatus as SyncingSyncStatus).height;
     } catch (e, s) {
-      Logging.instance.log("$e $s", level: LogLevel.Warning);
+      // Logging.instance.log("$e $s", level: LogLevel.Warning);
     }
     final cachedHeight =
         DB.instance.get<dynamic>(boxName: walletId, key: "storedSyncingHeight")
@@ -418,7 +418,7 @@ class WowneroWallet extends CoinServiceAPI {
       try {
         progress = (walletBase!.syncStatus!).progress();
       } catch (e, s) {
-        Logging.instance.log("$e $s", level: LogLevel.Warning);
+        // Logging.instance.log("$e $s", level: LogLevel.Warning);
       }
       await _fetchTransactionData();
 

From b333253287c44beb6bc86428cdfe3f55eb938df9 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 19 Nov 2022 15:12:08 -0600
Subject: [PATCH 060/100] reduce minimum window height

---
 lib/main.dart | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/main.dart b/lib/main.dart
index 66b3bb974..6879b69c5 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -77,7 +77,7 @@ void main() async {
 
   if (Util.isDesktop) {
     setWindowTitle('Stack Wallet');
-    setWindowMinSize(const Size(1220, 1100));
+    setWindowMinSize(const Size(1220, 1000));
     setWindowMaxSize(Size.infinite);
   }
 

From e2a172f7477550da845224003325da7bfbce35c5 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Sat, 19 Nov 2022 18:04:53 -0600
Subject: [PATCH 061/100] firo private/public balance desktop toggle

---
 assets/images/glasses-hidden.png              | Bin 0 -> 1060 bytes
 assets/images/glasses.png                     | Bin 0 -> 1955 bytes
 .../desktop_balance_toggle_button.dart        |  60 +++
 .../sub_widgets/desktop_wallet_summary.dart   | 375 +++++++-----------
 lib/utilities/assets.dart                     |   3 +
 pubspec.yaml                                  |   2 +
 6 files changed, 215 insertions(+), 225 deletions(-)
 create mode 100644 assets/images/glasses-hidden.png
 create mode 100644 assets/images/glasses.png
 create mode 100644 lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart

diff --git a/assets/images/glasses-hidden.png b/assets/images/glasses-hidden.png
new file mode 100644
index 0000000000000000000000000000000000000000..9176cc69b914fb6b435fe881fd4987835a0fd5dc
GIT binary patch
literal 1060
zcmeAS@N?(olHy`uVBq!ia0vp^HXzKw1|+Ti+$;i8Ea{HEjtmSN`?>!lvI6-E$sR$z
z3=CCj3=9n|3=F@3LJcn%7)lKo7+xg+b<JR45HFasD-dK5TavfC3&Vd9T(EcfWS|Ip
ziKnkC`!gmfA#Qn#&!RvBm^D0I978hhy}fZZJ0?`(_(y+ZwT&*^T_Kt*8^v4}zBn|s
zgS%Ys5A&U0;vGA}1Y9mG^**?Cg@Rs}NMN9W%SzsBZrvT7x2A`z{&seW=Pb{4-NkuD
z#ygE?s+2G3e$L%)U7Y^zukHTNpXP`+DR3a69ZPS9*IE4fA^i0FUx~xAKX=J1OT4Qn
z6V;A5CM2evDrp{g;LFLA`<hM~PATk3FnK-w>9?AEiM4&lZ%393nj6eNt<+`IRx3Jj
z`A3<)2MX`bC>`Fx>nzLUYIgVBvFV#G?BCJk{ew5%pnLy@3IC%*dU&6A?PceGFtNtA
zV|S5E^34|>eM>`g*PMxR*SY@DJne&>-9-6m@!y2z-3+yVc{a<e$~Jy_Q9+SvUz#)f
zlDMn4THW;L9crF&z$vrB_Z46Bf~jX^Brg2^ooHDd^M09j1+)6U<qTZXcdIVUIrREc
z#I;=}<>&UcAA4wHcRbO?MB!t0g?Ro$<;*$q(~6EN{17>x+%?6<db7#O{qlzoGjlu;
z-J{l<9rUPDF#p!9mT#wY=1raS?3d5Rd6nA1$9eWiHQdY&S{5_c&NA|qXpr_FV}`x!
zKL)pN*A4bP$q&@cKWFXEdPgZg-{ND(asu*q1PR-FUv{5-=0VZfzpEqHd)~^5D(`;C
zwRzV2w9BuS?+cxi7x7xFZsqTVvmbWfED7H7QFnIso==rtn{8i}&$-?Cu(IZQ0>ks|
zmG?{dHfipg9#vU=cxu%A2~o>9)vl<onPgdWbHcT#YpY{#@O-WKz*3j1(7?K9x%bo1
zWy|@Otjt~?b0FpE-CAk8?#H|=1w8R3+zSq|*yT99H;xqw3kRB1?|$pi+i9A6v~s1l
zKVG)w+21t&D)EoodZ*qI+m(0p)30Ctnh#};-mUuHG0DlR>i9>dx-}t5x>LXYNnL4u
zue~ty^$q^)OCPEw<-cEgy|ZrZoTi?~o;Gd2H~+lYb%Qtavc0;lf!}kZ{c~?h*<Skh
z<6=zTg9#-P25PbrB9~0cTxZq!d7geKIrVa{tn@n}pVQBjr#X3fyv^B{-)wzBX4B6n
zOKox^Pwwi?WOEc?furp<{~34v{Bv>IuQX?1Hc~BdjVMV;EJ?LWE=mPb3`Pb<M!E(@
zx<+Oph89+ahE_)A+6D$z1_t}Z-)}?Fkei>9nO2Eg!#S^TP<g=M>FVdQ&MBb@01M61
A`2YX_

literal 0
HcmV?d00001

diff --git a/assets/images/glasses.png b/assets/images/glasses.png
new file mode 100644
index 0000000000000000000000000000000000000000..8c9e7dc276660d6b8284916943c78137a0d6ad2f
GIT binary patch
literal 1955
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
Fz~8{u`yl`T

literal 0
HcmV?d00001

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart
new file mode 100644
index 000000000..9c890b223
--- /dev/null
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart
@@ -0,0 +1,60 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/constants.dart';
+import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+
+class DesktopBalanceToggleButton extends ConsumerWidget {
+  const DesktopBalanceToggleButton({
+    Key? key,
+    this.onPressed,
+  }) : super(key: key);
+
+  final VoidCallback? onPressed;
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    return SizedBox(
+      height: 22,
+      width: 22,
+      child: MaterialButton(
+        color: Theme.of(context).extension<StackColors>()!.buttonBackSecondary,
+        splashColor: Theme.of(context).extension<StackColors>()!.highlight,
+        onPressed: () {
+          if (ref.read(walletBalanceToggleStateProvider.state).state ==
+              WalletBalanceToggleState.available) {
+            ref.read(walletBalanceToggleStateProvider.state).state =
+                WalletBalanceToggleState.full;
+          } else {
+            ref.read(walletBalanceToggleStateProvider.state).state =
+                WalletBalanceToggleState.available;
+          }
+          onPressed?.call();
+        },
+        elevation: 0,
+        highlightElevation: 0,
+        hoverElevation: 0,
+        padding: EdgeInsets.zero,
+        materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+        shape: RoundedRectangleBorder(
+          borderRadius: BorderRadius.circular(
+            Constants.size.circularBorderRadius,
+          ),
+        ),
+        child: Center(
+          child: Image(
+            image: AssetImage(
+              ref.watch(walletBalanceToggleStateProvider.state).state ==
+                      WalletBalanceToggleState.available
+                  ? Assets.png.glassesHidden
+                  : Assets.png.glasses,
+            ),
+            width: 16,
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart
index f4bfed976..d6e99ce70 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart
@@ -1,13 +1,15 @@
 import 'package:decimal/decimal.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart';
 import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_refresh_button.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_balance_toggle_button.dart';
 import 'package:stackwallet/providers/providers.dart';
+import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.dart';
 import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
 import 'package:stackwallet/services/coins/manager.dart';
 import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
+import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart';
 import 'package:stackwallet/utilities/format.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
@@ -33,19 +35,6 @@ class _WDesktopWalletSummaryState extends State<DesktopWalletSummary> {
   late final String walletId;
   late final ChangeNotifierProvider<Manager> managerProvider;
 
-  void showSheet() {
-    showModalBottomSheet<dynamic>(
-      backgroundColor: Colors.transparent,
-      context: context,
-      shape: const RoundedRectangleBorder(
-        borderRadius: BorderRadius.vertical(
-          top: Radius.circular(20),
-        ),
-      ),
-      builder: (_) => WalletBalanceToggleSheet(walletId: walletId),
-    );
-  }
-
   Decimal? _balanceTotalCached;
   Decimal? _balanceCached;
 
@@ -59,225 +48,161 @@ class _WDesktopWalletSummaryState extends State<DesktopWalletSummary> {
   @override
   Widget build(BuildContext context) {
     debugPrint("BUILD: $runtimeType");
-    return Row(
-      crossAxisAlignment: CrossAxisAlignment.start,
-      children: [
-        Column(
+    return Consumer(
+      builder: (context, ref, __) {
+        final Coin coin =
+            ref.watch(managerProvider.select((value) => value.coin));
+        return Row(
+          crossAxisAlignment: CrossAxisAlignment.start,
           children: [
-            Consumer(
-              builder: (_, ref, __) {
-                final Coin coin =
-                    ref.watch(managerProvider.select((value) => value.coin));
-                final externalCalls = ref.watch(prefsChangeNotifierProvider
-                    .select((value) => value.externalCalls));
+            Column(
+              children: [
+                Consumer(
+                  builder: (_, ref, __) {
+                    final externalCalls = ref.watch(prefsChangeNotifierProvider
+                        .select((value) => value.externalCalls));
 
-                Future<Decimal>? totalBalanceFuture;
-                Future<Decimal>? availableBalanceFuture;
-                if (coin == Coin.firo || coin == Coin.firoTestNet) {
-                  final firoWallet =
-                      ref.watch(managerProvider.select((value) => value.wallet))
+                    Future<Decimal>? totalBalanceFuture;
+                    Future<Decimal>? availableBalanceFuture;
+                    if (coin == Coin.firo || coin == Coin.firoTestNet) {
+                      final firoWallet = ref.watch(
+                              managerProvider.select((value) => value.wallet))
                           as FiroWallet;
-                  totalBalanceFuture = firoWallet.availablePublicBalance();
-                  availableBalanceFuture = firoWallet.availablePrivateBalance();
-                } else {
-                  totalBalanceFuture = ref.watch(
-                      managerProvider.select((value) => value.totalBalance));
-
-                  availableBalanceFuture = ref.watch(managerProvider
-                      .select((value) => value.availableBalance));
-                }
-
-                final locale = ref.watch(localeServiceChangeNotifierProvider
-                    .select((value) => value.locale));
-
-                final baseCurrency = ref.watch(prefsChangeNotifierProvider
-                    .select((value) => value.currency));
-
-                final priceTuple = ref.watch(priceAnd24hChangeNotifierProvider
-                    .select((value) => value.getPrice(coin)));
-
-                final _showAvailable = false;
-                // ref.watch(walletBalanceToggleStateProvider.state).state ==
-                //     WalletBalanceToggleState.available;
-
-                return FutureBuilder(
-                  future: _showAvailable
-                      ? availableBalanceFuture
-                      : totalBalanceFuture,
-                  builder: (fbContext, AsyncSnapshot<Decimal> snapshot) {
-                    if (snapshot.connectionState == ConnectionState.done &&
-                        snapshot.hasData &&
-                        snapshot.data != null) {
-                      if (_showAvailable) {
-                        _balanceCached = snapshot.data!;
-                      } else {
-                        _balanceTotalCached = snapshot.data!;
-                      }
-                    }
-                    Decimal? balanceToShow =
-                        _showAvailable ? _balanceCached : _balanceTotalCached;
-
-                    if (balanceToShow != null) {
-                      return Column(
-                        crossAxisAlignment: CrossAxisAlignment.start,
-                        children: [
-                          // GestureDetector(
-                          //   onTap: showSheet,
-                          //   child: Row(
-                          //     children: [
-                          //       if (coin == Coin.firo ||
-                          //           coin == Coin.firoTestNet)
-                          //         Text(
-                          //           "${_showAvailable ? "Private" : "Public"} Balance",
-                          //           style: STextStyles.subtitle500(context)
-                          //               .copyWith(
-                          //             color: Theme.of(context)
-                          //                 .extension<StackColors>()!
-                          //                 .textFavoriteCard,
-                          //           ),
-                          //         ),
-                          //       if (coin != Coin.firo &&
-                          //           coin != Coin.firoTestNet)
-                          //         Text(
-                          //           "${_showAvailable ? "Available" : "Full"} Balance",
-                          //           style: STextStyles.subtitle500(context)
-                          //               .copyWith(
-                          //             color: Theme.of(context)
-                          //                 .extension<StackColors>()!
-                          //                 .textFavoriteCard,
-                          //           ),
-                          //         ),
-                          //       const SizedBox(
-                          //         width: 4,
-                          //       ),
-                          //       SvgPicture.asset(
-                          //         Assets.svg.chevronDown,
-                          //         color: Theme.of(context)
-                          //             .extension<StackColors>()!
-                          //             .textFavoriteCard,
-                          //         width: 8,
-                          //         height: 4,
-                          //       ),
-                          //     ],
-                          //   ),
-                          // ),
-                          FittedBox(
-                            fit: BoxFit.scaleDown,
-                            child: Text(
-                              "${Format.localizedStringAsFixed(
-                                value: balanceToShow,
-                                locale: locale,
-                                decimalPlaces: 8,
-                              )} ${coin.ticker}",
-                              style: STextStyles.desktopH3(context),
-                            ),
-                          ),
-                          if (externalCalls)
-                            Text(
-                              "${Format.localizedStringAsFixed(
-                                value: priceTuple.item1 * balanceToShow,
-                                locale: locale,
-                                decimalPlaces: 2,
-                              )} $baseCurrency",
-                              style: STextStyles.desktopTextExtraSmall(context)
-                                  .copyWith(
-                                color: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .textSubtitle1,
-                              ),
-                            ),
-                        ],
-                      );
+                      totalBalanceFuture = firoWallet.availablePublicBalance();
+                      availableBalanceFuture =
+                          firoWallet.availablePrivateBalance();
                     } else {
-                      return Column(
-                        crossAxisAlignment: CrossAxisAlignment.start,
-                        children: [
-                          // GestureDetector(
-                          //   onTap: showSheet,
-                          //   child: Row(
-                          //     children: [
-                          //       if (coin == Coin.firo ||
-                          //           coin == Coin.firoTestNet)
-                          //         Text(
-                          //           "${_showAvailable ? "Private" : "Public"} Balance",
-                          //           style: STextStyles.subtitle500(context)
-                          //               .copyWith(
-                          //             color: Theme.of(context)
-                          //                 .extension<StackColors>()!
-                          //                 .textFavoriteCard,
-                          //           ),
-                          //         ),
-                          //       if (coin != Coin.firo &&
-                          //           coin != Coin.firoTestNet)
-                          //         Text(
-                          //           "${_showAvailable ? "Available" : "Full"} Balance",
-                          //           style: STextStyles.subtitle500(context)
-                          //               .copyWith(
-                          //             color: Theme.of(context)
-                          //                 .extension<StackColors>()!
-                          //                 .textFavoriteCard,
-                          //           ),
-                          //         ),
-                          //       const SizedBox(
-                          //         width: 4,
-                          //       ),
-                          //       SvgPicture.asset(
-                          //         Assets.svg.chevronDown,
-                          //         width: 8,
-                          //         height: 4,
-                          //         color: Theme.of(context)
-                          //             .extension<StackColors>()!
-                          //             .textFavoriteCard,
-                          //       ),
-                          //     ],
-                          //   ),
-                          // ),
-                          AnimatedText(
-                            stringsToLoopThrough: const [
-                              "Loading balance   ",
-                              "Loading balance.  ",
-                              "Loading balance.. ",
-                              "Loading balance..."
-                            ],
-                            style: STextStyles.desktopH3(context).copyWith(
-                              fontSize: 24,
-                              color: Theme.of(context)
-                                  .extension<StackColors>()!
-                                  .textDark,
-                            ),
-                          ),
-                          if (externalCalls)
-                            AnimatedText(
-                              stringsToLoopThrough: const [
-                                "Loading balance   ",
-                                "Loading balance.  ",
-                                "Loading balance.. ",
-                                "Loading balance..."
-                              ],
-                              style: STextStyles.desktopTextExtraSmall(context)
-                                  .copyWith(
-                                color: Theme.of(context)
-                                    .extension<StackColors>()!
-                                    .textSubtitle1,
-                              ),
-                            ),
-                        ],
-                      );
+                      totalBalanceFuture = ref.watch(managerProvider
+                          .select((value) => value.totalBalance));
+
+                      availableBalanceFuture = ref.watch(managerProvider
+                          .select((value) => value.availableBalance));
                     }
+
+                    final locale = ref.watch(localeServiceChangeNotifierProvider
+                        .select((value) => value.locale));
+
+                    final baseCurrency = ref.watch(prefsChangeNotifierProvider
+                        .select((value) => value.currency));
+
+                    final priceTuple = ref.watch(
+                        priceAnd24hChangeNotifierProvider
+                            .select((value) => value.getPrice(coin)));
+
+                    final _showAvailable = ref
+                            .watch(walletBalanceToggleStateProvider.state)
+                            .state ==
+                        WalletBalanceToggleState.available;
+
+                    return FutureBuilder(
+                      future: _showAvailable
+                          ? availableBalanceFuture
+                          : totalBalanceFuture,
+                      builder: (fbContext, AsyncSnapshot<Decimal> snapshot) {
+                        if (snapshot.connectionState == ConnectionState.done &&
+                            snapshot.hasData &&
+                            snapshot.data != null) {
+                          if (_showAvailable) {
+                            _balanceCached = snapshot.data!;
+                          } else {
+                            _balanceTotalCached = snapshot.data!;
+                          }
+                        }
+                        Decimal? balanceToShow = _showAvailable
+                            ? _balanceCached
+                            : _balanceTotalCached;
+
+                        if (balanceToShow != null) {
+                          return Column(
+                            crossAxisAlignment: CrossAxisAlignment.start,
+                            children: [
+                              FittedBox(
+                                fit: BoxFit.scaleDown,
+                                child: Text(
+                                  "${Format.localizedStringAsFixed(
+                                    value: balanceToShow,
+                                    locale: locale,
+                                    decimalPlaces: 8,
+                                  )} ${coin.ticker}",
+                                  style: STextStyles.desktopH3(context),
+                                ),
+                              ),
+                              if (externalCalls)
+                                Text(
+                                  "${Format.localizedStringAsFixed(
+                                    value: priceTuple.item1 * balanceToShow,
+                                    locale: locale,
+                                    decimalPlaces: 2,
+                                  )} $baseCurrency",
+                                  style:
+                                      STextStyles.desktopTextExtraSmall(context)
+                                          .copyWith(
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textSubtitle1,
+                                  ),
+                                ),
+                            ],
+                          );
+                        } else {
+                          return Column(
+                            crossAxisAlignment: CrossAxisAlignment.start,
+                            children: [
+                              AnimatedText(
+                                stringsToLoopThrough: const [
+                                  "Loading balance   ",
+                                  "Loading balance.  ",
+                                  "Loading balance.. ",
+                                  "Loading balance..."
+                                ],
+                                style: STextStyles.desktopH3(context).copyWith(
+                                  fontSize: 24,
+                                  color: Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark,
+                                ),
+                              ),
+                              if (externalCalls)
+                                AnimatedText(
+                                  stringsToLoopThrough: const [
+                                    "Loading balance   ",
+                                    "Loading balance.  ",
+                                    "Loading balance.. ",
+                                    "Loading balance..."
+                                  ],
+                                  style:
+                                      STextStyles.desktopTextExtraSmall(context)
+                                          .copyWith(
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textSubtitle1,
+                                  ),
+                                ),
+                            ],
+                          );
+                        }
+                      },
+                    );
                   },
-                );
-              },
+                ),
+              ],
             ),
+            if (coin == Coin.firo || coin == Coin.firoTestNet)
+              const SizedBox(
+                width: 8,
+              ),
+            if (coin == Coin.firo || coin == Coin.firoTestNet)
+              const DesktopBalanceToggleButton(),
+            const SizedBox(
+              width: 8,
+            ),
+            WalletRefreshButton(
+              walletId: walletId,
+              initialSyncStatus: widget.initialSyncStatus,
+            )
           ],
-        ),
-        const SizedBox(
-          width: 8,
-        ),
-        WalletRefreshButton(
-          walletId: walletId,
-          initialSyncStatus: widget.initialSyncStatus,
-        )
-      ],
+        );
+      },
     );
   }
 }
diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart
index 6fbe61005..149d46b3c 100644
--- a/lib/utilities/assets.dart
+++ b/lib/utilities/assets.dart
@@ -231,6 +231,9 @@ class _PNG {
   String get bitcoincash => "assets/images/bitcoincash.png";
   String get namecoin => "assets/images/namecoin.png";
 
+  String get glasses => "assets/images/glasses.png";
+  String get glassesHidden => "assets/images/glasses-hidden.png";
+
   String imageFor({required Coin coin}) {
     switch (coin) {
       case Coin.bitcoin:
diff --git a/pubspec.yaml b/pubspec.yaml
index e8f417586..af4370d99 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -202,6 +202,8 @@ flutter:
     - assets/images/epic-cash.png
     - assets/images/bitcoincash.png
     - assets/images/namecoin.png
+    - assets/images/glasses.png
+    - assets/images/glasses-hidden.png
     - assets/svg/plus.svg
     - assets/svg/gear.svg
     - assets/svg/bell.svg

From 345ed958e080999ac2696ca24850d0d5944bbc39 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 07:44:45 -0600
Subject: [PATCH 062/100] initial window size linux

---
 lib/main.dart           | 2 +-
 linux/my_application.cc | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/main.dart b/lib/main.dart
index 6879b69c5..728152951 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -77,7 +77,7 @@ void main() async {
 
   if (Util.isDesktop) {
     setWindowTitle('Stack Wallet');
-    setWindowMinSize(const Size(1220, 1000));
+    setWindowMinSize(const Size(1220, 900));
     setWindowMaxSize(Size.infinite);
   }
 
diff --git a/linux/my_application.cc b/linux/my_application.cc
index 280895e03..9cb3acebd 100644
--- a/linux/my_application.cc
+++ b/linux/my_application.cc
@@ -47,7 +47,7 @@ static void my_application_activate(GApplication* application) {
     gtk_window_set_title(window, "Stack Wallet");
   }
 
-  gtk_window_set_default_size(window, 720, 1280);
+  gtk_window_set_default_size(window, 1220, 900);
   gtk_widget_show(GTK_WIDGET(window));
 
   g_autoptr(FlDartProject) project = fl_dart_project_new();

From b22b4195d6bf3cd4f7bec097a58c0cef7fb737d9 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 09:15:13 -0600
Subject: [PATCH 063/100] desktop exchange steps scaffolding

---
 lib/pages/exchange_view/exchange_form.dart    |  23 ++--
 .../exchange_steps/step_scaffold.dart         |  28 +++--
 .../subwidgets/desktop_step_1.dart            | 104 ++++++++++++++++++
 .../subwidgets/desktop_step_2.dart            |  66 +++++++++++
 .../subwidgets/desktop_step_3.dart            |  91 +++++++++++++++
 .../subwidgets/desktop_step_4.dart            |  98 +++++++++++++++++
 .../subwidgets/step_one_item.dart             |  38 +++++++
 .../desktop_exchange_steps_indicator.dart     |  32 +++---
 8 files changed, 452 insertions(+), 28 deletions(-)
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart

diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart
index 2d89c7660..148c74920 100644
--- a/lib/pages/exchange_view/exchange_form.dart
+++ b/lib/pages/exchange_view/exchange_form.dart
@@ -19,12 +19,13 @@ import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_provider_op
 import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
 import 'package:stackwallet/pages/exchange_view/sub_widgets/rate_type_toggle.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart';
 import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
 import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
-import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
 import 'package:stackwallet/utilities/logger.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
@@ -913,10 +914,14 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
           await showDialog<void>(
             context: context,
             builder: (context) {
-              return const DesktopDialog(
-                maxWidth: 700,
+              return DesktopDialog(
+                maxWidth: 720,
+                maxHeight: double.infinity,
                 child: StepScaffold(
-                  step: 1,
+                  step: 2,
+                  body: DesktopStep2(
+                    model: model,
+                  ),
                 ),
               );
             },
@@ -936,10 +941,14 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
           await showDialog<void>(
             context: context,
             builder: (context) {
-              return const DesktopDialog(
-                maxWidth: 700,
+              return DesktopDialog(
+                maxWidth: 720,
+                maxHeight: double.infinity,
                 child: StepScaffold(
-                  step: 0,
+                  step: 1,
+                  body: DesktopStep1(
+                    model: model,
+                  ),
                 ),
               );
             },
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart
index 09aea9dbf..62a293c27 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart
@@ -4,8 +4,13 @@ import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 
 class StepScaffold extends StatefulWidget {
-  const StepScaffold({Key? key, required this.step}) : super(key: key);
+  const StepScaffold({
+    Key? key,
+    required this.body,
+    required this.step,
+  }) : super(key: key);
 
+  final Widget body;
   final int step;
 
   @override
@@ -24,11 +29,13 @@ class _StepScaffoldState extends State<StepScaffold> {
   @override
   Widget build(BuildContext context) {
     return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
       children: [
         Row(
           children: [
             const AppBarBackButton(
               isCompact: true,
+              iconSize: 23,
             ),
             Text(
               "Exchange XXX to XXX",
@@ -37,17 +44,24 @@ class _StepScaffoldState extends State<StepScaffold> {
           ],
         ),
         const SizedBox(
-          height: 32,
+          height: 12,
         ),
-        DesktopExchangeStepsIndicator(
-          currentStep: currentStep,
+        Padding(
+          padding: const EdgeInsets.symmetric(
+            horizontal: 32,
+          ),
+          child: DesktopExchangeStepsIndicator(
+            currentStep: currentStep,
+          ),
         ),
         const SizedBox(
           height: 32,
         ),
-        Container(
-          height: 200,
-          color: Colors.red,
+        Padding(
+          padding: const EdgeInsets.symmetric(
+            horizontal: 32,
+          ),
+          child: widget.body,
         ),
       ],
     );
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
new file mode 100644
index 000000000..7334cae05
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
@@ -0,0 +1,104 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+
+class DesktopStep1 extends StatelessWidget {
+  const DesktopStep1({
+    Key? key,
+    required this.model,
+  }) : super(key: key);
+
+  final IncompleteExchangeModel model;
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        Text(
+          "Confirm amount",
+          style: STextStyles.desktopTextMedium(context),
+        ),
+        const SizedBox(
+          height: 8,
+        ),
+        Text(
+          "Network fees and other exchange charges are included in the rate.",
+          style: STextStyles.desktopTextExtraExtraSmall(context),
+        ),
+        const SizedBox(
+          height: 20,
+        ),
+        RoundedWhiteContainer(
+          borderColor: Theme.of(context).extension<StackColors>()!.background,
+          padding: const EdgeInsets.all(0),
+          child: Column(
+            children: [
+              const StepOneItem(
+                label: "Exchange",
+                value: "lol",
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              const StepOneItem(
+                label: "You send",
+                value: "lol",
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              const StepOneItem(
+                label: "You receive",
+                value: "lol",
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              const StepOneItem(
+                label: "Rate",
+                value: "lol",
+              ),
+            ],
+          ),
+        ),
+        Padding(
+          padding: const EdgeInsets.only(
+            top: 20,
+            bottom: 32,
+          ),
+          child: Row(
+            children: [
+              Expanded(
+                child: SecondaryButton(
+                  label: "Back",
+                  buttonHeight: ButtonHeight.l,
+                  onPressed: Navigator.of(context).pop,
+                ),
+              ),
+              const SizedBox(
+                width: 16,
+              ),
+              Expanded(
+                child: PrimaryButton(
+                  label: "Next",
+                  buttonHeight: ButtonHeight.l,
+                  onPressed: () {
+                    // todo
+                  },
+                ),
+              ),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
new file mode 100644
index 000000000..c9072cb76
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
@@ -0,0 +1,66 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+
+class DesktopStep2 extends StatelessWidget {
+  const DesktopStep2({
+    Key? key,
+    required this.model,
+  }) : super(key: key);
+
+  final IncompleteExchangeModel model;
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        Text(
+          "Enter exchange details",
+          style: STextStyles.desktopTextMedium(context),
+        ),
+        const SizedBox(
+          height: 8,
+        ),
+        Text(
+          "Enter your recipient and refund addresses",
+          style: STextStyles.desktopTextExtraExtraSmall(context),
+        ),
+        const SizedBox(
+          height: 20,
+        ),
+        //
+        Padding(
+          padding: const EdgeInsets.only(
+            top: 20,
+            bottom: 32,
+          ),
+          child: Row(
+            children: [
+              Expanded(
+                child: SecondaryButton(
+                  label: "Back",
+                  buttonHeight: ButtonHeight.l,
+                  onPressed: Navigator.of(context).pop,
+                ),
+              ),
+              const SizedBox(
+                width: 16,
+              ),
+              Expanded(
+                child: PrimaryButton(
+                  label: "Next",
+                  buttonHeight: ButtonHeight.l,
+                  onPressed: () {
+                    // todo
+                  },
+                ),
+              ),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
new file mode 100644
index 000000000..1e2743ef5
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
@@ -0,0 +1,91 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+
+class DesktopStep3 extends StatelessWidget {
+  const DesktopStep3({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        Text(
+          "Confirm exchange details",
+          style: STextStyles.desktopTextMedium(context),
+        ),
+        const SizedBox(
+          height: 20,
+        ),
+        RoundedWhiteContainer(
+          borderColor: Theme.of(context).extension<StackColors>()!.background,
+          padding: const EdgeInsets.all(0),
+          child: Column(
+            children: [
+              const StepOneItem(
+                label: "Exchange",
+                value: "lol",
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              const StepOneItem(
+                label: "You send",
+                value: "lol",
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              const StepOneItem(
+                label: "You receive",
+                value: "lol",
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              const StepOneItem(
+                label: "Rate",
+                value: "lol",
+              ),
+            ],
+          ),
+        ),
+        Padding(
+          padding: const EdgeInsets.only(
+            top: 20,
+            bottom: 32,
+          ),
+          child: Row(
+            children: [
+              Expanded(
+                child: SecondaryButton(
+                  label: "Back",
+                  buttonHeight: ButtonHeight.l,
+                  onPressed: Navigator.of(context).pop,
+                ),
+              ),
+              const SizedBox(
+                width: 16,
+              ),
+              Expanded(
+                child: PrimaryButton(
+                  label: "Confirm",
+                  buttonHeight: ButtonHeight.l,
+                  onPressed: () {
+                    // todo
+                  },
+                ),
+              ),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
new file mode 100644
index 000000000..8604e7c23
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
@@ -0,0 +1,98 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+
+class DesktopStep4 extends StatelessWidget {
+  const DesktopStep4({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        Text(
+          "Confirm amount",
+          style: STextStyles.desktopTextMedium(context),
+        ),
+        const SizedBox(
+          height: 8,
+        ),
+        Text(
+          "Network fees and other exchange charges are included in the rate.",
+          style: STextStyles.desktopTextExtraExtraSmall(context),
+        ),
+        const SizedBox(
+          height: 20,
+        ),
+        RoundedWhiteContainer(
+          borderColor: Theme.of(context).extension<StackColors>()!.background,
+          padding: const EdgeInsets.all(0),
+          child: Column(
+            children: [
+              const StepOneItem(
+                label: "Exchange",
+                value: "lol",
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              const StepOneItem(
+                label: "You send",
+                value: "lol",
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              const StepOneItem(
+                label: "You receive",
+                value: "lol",
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              const StepOneItem(
+                label: "Rate",
+                value: "lol",
+              ),
+            ],
+          ),
+        ),
+        Padding(
+          padding: const EdgeInsets.only(
+            top: 20,
+            bottom: 32,
+          ),
+          child: Row(
+            children: [
+              Expanded(
+                child: SecondaryButton(
+                  label: "Send from Stack Wallet",
+                  buttonHeight: ButtonHeight.l,
+                  onPressed: Navigator.of(context).pop,
+                ),
+              ),
+              const SizedBox(
+                width: 16,
+              ),
+              Expanded(
+                child: PrimaryButton(
+                  label: "Show QR code",
+                  buttonHeight: ButtonHeight.l,
+                  onPressed: () {
+                    // todo
+                  },
+                ),
+              ),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart
new file mode 100644
index 000000000..001383a17
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+
+class StepOneItem extends StatelessWidget {
+  const StepOneItem({
+    Key? key,
+    required this.label,
+    required this.value,
+    this.padding = const EdgeInsets.all(16),
+  }) : super(key: key);
+
+  final String label;
+  final String value;
+  final EdgeInsets padding;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: padding,
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: [
+          Text(
+            label,
+            style: STextStyles.desktopTextExtraExtraSmall(context),
+          ),
+          Text(
+            value,
+            style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+              color: Theme.of(context).extension<StackColors>()!.textDark,
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart
index 44831bb4b..ddcd2e6c4 100644
--- a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart
@@ -22,9 +22,9 @@ class DesktopExchangeStepsIndicator extends StatelessWidget {
     }
   }
 
-  static const double verticalSpacing = 4;
+  static const double verticalSpacing = 6;
   static const double horizontalSpacing = 16;
-  static const double barHeight = 6;
+  static const double barHeight = 4;
 
   @override
   Widget build(BuildContext context) {
@@ -35,16 +35,17 @@ class DesktopExchangeStepsIndicator extends StatelessWidget {
             children: [
               Text(
                 "Confirm amount",
-                style: STextStyles.desktopTextSmall(context).copyWith(
-                  color: getColor(context, 0),
+                style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+                  color: getColor(context, 1),
                 ),
               ),
               const SizedBox(
                 height: verticalSpacing,
               ),
               RoundedContainer(
-                color: getColor(context, 0),
+                color: getColor(context, 1),
                 height: barHeight,
+                width: double.infinity,
               ),
             ],
           ),
@@ -57,16 +58,17 @@ class DesktopExchangeStepsIndicator extends StatelessWidget {
             children: [
               Text(
                 "Enter details",
-                style: STextStyles.desktopTextSmall(context).copyWith(
-                  color: getColor(context, 1),
+                style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+                  color: getColor(context, 2),
                 ),
               ),
               const SizedBox(
                 height: verticalSpacing,
               ),
               RoundedContainer(
-                color: getColor(context, 1),
+                color: getColor(context, 2),
                 height: barHeight,
+                width: double.infinity,
               ),
             ],
           ),
@@ -79,16 +81,17 @@ class DesktopExchangeStepsIndicator extends StatelessWidget {
             children: [
               Text(
                 "Confirm details",
-                style: STextStyles.desktopTextSmall(context).copyWith(
-                  color: getColor(context, 2),
+                style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+                  color: getColor(context, 3),
                 ),
               ),
               const SizedBox(
                 height: verticalSpacing,
               ),
               RoundedContainer(
-                color: getColor(context, 2),
+                color: getColor(context, 3),
                 height: barHeight,
+                width: double.infinity,
               ),
             ],
           ),
@@ -101,16 +104,17 @@ class DesktopExchangeStepsIndicator extends StatelessWidget {
             children: [
               Text(
                 "Complete exchange",
-                style: STextStyles.desktopTextSmall(context).copyWith(
-                  color: getColor(context, 3),
+                style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+                  color: getColor(context, 4),
                 ),
               ),
               const SizedBox(
                 height: verticalSpacing,
               ),
               RoundedContainer(
-                color: getColor(context, 3),
+                color: getColor(context, 4),
                 height: barHeight,
+                width: double.infinity,
               ),
             ],
           ),

From 11845b8b05b712cc6a9a931f44c5fb0ab7577de7 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 09:23:11 -0600
Subject: [PATCH 064/100] populate desktop step one trade info

---
 .../subwidgets/desktop_step_1.dart            | 29 ++++++++++++-------
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
index 7334cae05..1f892dd52 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
@@ -1,13 +1,16 @@
 import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
+import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart';
+import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 
-class DesktopStep1 extends StatelessWidget {
+class DesktopStep1 extends ConsumerWidget {
   const DesktopStep1({
     Key? key,
     required this.model,
@@ -16,7 +19,7 @@ class DesktopStep1 extends StatelessWidget {
   final IncompleteExchangeModel model;
 
   @override
-  Widget build(BuildContext context) {
+  Widget build(BuildContext context, WidgetRef ref) {
     return Column(
       children: [
         Text(
@@ -38,33 +41,37 @@ class DesktopStep1 extends StatelessWidget {
           padding: const EdgeInsets.all(0),
           child: Column(
             children: [
-              const StepOneItem(
+              StepOneItem(
                 label: "Exchange",
-                value: "lol",
+                value: ref.watch(currentExchangeNameStateProvider.state).state,
               ),
               Container(
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const StepOneItem(
+              StepOneItem(
                 label: "You send",
-                value: "lol",
+                value:
+                    "${model.sendAmount.toStringAsFixed(8)} ${model.sendTicker.toUpperCase()}",
               ),
               Container(
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const StepOneItem(
+              StepOneItem(
                 label: "You receive",
-                value: "lol",
+                value:
+                    "~${model.receiveAmount.toStringAsFixed(8)} ${model.receiveTicker.toUpperCase()}",
               ),
               Container(
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const StepOneItem(
-                label: "Rate",
-                value: "lol",
+              StepOneItem(
+                label: model.rateType == ExchangeRateType.estimated
+                    ? "Estimated rate"
+                    : "Fixed rate",
+                value: model.rateInfo,
               ),
             ],
           ),

From 2654d50e407b74916ad5ef95b4f27327518247ca Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 09:41:16 -0600
Subject: [PATCH 065/100] populate desktop step two trade info

---
 .../subwidgets/desktop_step_2.dart            | 423 +++++++++++++++++-
 1 file changed, 421 insertions(+), 2 deletions(-)

diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
index c9072cb76..e1c5a5620 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
@@ -1,16 +1,199 @@
 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
+import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
+import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart';
+import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
+import 'package:stackwallet/providers/exchange/exchange_flow_is_active_state_provider.dart';
+import 'package:stackwallet/providers/exchange/exchange_send_from_wallet_id_provider.dart';
+import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/utilities/clipboard_interface.dart';
+import 'package:stackwallet/utilities/constants.dart';
+import 'package:stackwallet/utilities/enums/coin_enum.dart';
+import 'package:stackwallet/utilities/logger.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/icon_widgets/addressbook_icon.dart';
+import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart';
+import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+import 'package:stackwallet/widgets/stack_text_field.dart';
+import 'package:stackwallet/widgets/textfield_icon_button.dart';
 
-class DesktopStep2 extends StatelessWidget {
+class DesktopStep2 extends ConsumerStatefulWidget {
   const DesktopStep2({
     Key? key,
     required this.model,
+    this.clipboard = const ClipboardWrapper(),
   }) : super(key: key);
 
   final IncompleteExchangeModel model;
+  final ClipboardInterface clipboard;
+
+  @override
+  ConsumerState<DesktopStep2> createState() => _DesktopStep2State();
+}
+
+class _DesktopStep2State extends ConsumerState<DesktopStep2> {
+  late final IncompleteExchangeModel model;
+  late final ClipboardInterface clipboard;
+
+  late final TextEditingController _toController;
+  late final TextEditingController _refundController;
+
+  late final FocusNode _toFocusNode;
+  late final FocusNode _refundFocusNode;
+
+  bool isStackCoin(String ticker) {
+    try {
+      coinFromTickerCaseInsensitive(ticker);
+      return true;
+    } on ArgumentError catch (_) {
+      return false;
+    }
+  }
+
+  void selectRecipientAddressFromStack() {
+    try {
+      final coin = coinFromTickerCaseInsensitive(
+        model.receiveTicker,
+      );
+      Navigator.of(context)
+          .pushNamed(
+        ChooseFromStackView.routeName,
+        arguments: coin,
+      )
+          .then((value) async {
+        if (value is String) {
+          final manager =
+              ref.read(walletsChangeNotifierProvider).getManager(value);
+
+          _toController.text = manager.walletName;
+          model.recipientAddress = await manager.currentReceivingAddress;
+        }
+      });
+    } catch (e, s) {
+      Logging.instance.log("$e\n$s", level: LogLevel.Info);
+    }
+  }
+
+  void selectRefundAddressFromStack() {
+    try {
+      final coin = coinFromTickerCaseInsensitive(
+        model.sendTicker,
+      );
+      Navigator.of(context)
+          .pushNamed(
+        ChooseFromStackView.routeName,
+        arguments: coin,
+      )
+          .then((value) async {
+        if (value is String) {
+          final manager =
+              ref.read(walletsChangeNotifierProvider).getManager(value);
+
+          _refundController.text = manager.walletName;
+          model.refundAddress = await manager.currentReceivingAddress;
+        }
+      });
+    } catch (e, s) {
+      Logging.instance.log("$e\n$s", level: LogLevel.Info);
+    }
+  }
+
+  void selectRecipientFromAddressBook() {
+    ref.read(exchangeFlowIsActiveStateProvider.state).state = true;
+    Navigator.of(context)
+        .pushNamed(
+      AddressBookView.routeName,
+    )
+        .then((_) {
+      ref.read(exchangeFlowIsActiveStateProvider.state).state = false;
+
+      final address =
+          ref.read(exchangeFromAddressBookAddressStateProvider.state).state;
+      if (address.isNotEmpty) {
+        _toController.text = address;
+        model.recipientAddress = _toController.text;
+        ref.read(exchangeFromAddressBookAddressStateProvider.state).state = "";
+      }
+    });
+  }
+
+  void selectRefundFromAddressBook() {
+    ref.read(exchangeFlowIsActiveStateProvider.state).state = true;
+    Navigator.of(context)
+        .pushNamed(
+      AddressBookView.routeName,
+    )
+        .then(
+      (_) {
+        ref.read(exchangeFlowIsActiveStateProvider.state).state = false;
+        final address =
+            ref.read(exchangeFromAddressBookAddressStateProvider.state).state;
+        if (address.isNotEmpty) {
+          _refundController.text = address;
+          model.refundAddress = _refundController.text;
+        }
+      },
+    );
+  }
+
+  @override
+  void initState() {
+    model = widget.model;
+    clipboard = widget.clipboard;
+
+    _toController = TextEditingController();
+    _refundController = TextEditingController();
+
+    _toFocusNode = FocusNode();
+    _refundFocusNode = FocusNode();
+
+    final tuple = ref.read(exchangeSendFromWalletIdStateProvider.state).state;
+    if (tuple != null) {
+      if (model.receiveTicker.toLowerCase() ==
+          tuple.item2.ticker.toLowerCase()) {
+        ref
+            .read(walletsChangeNotifierProvider)
+            .getManager(tuple.item1)
+            .currentReceivingAddress
+            .then((value) {
+          _toController.text = value;
+          model.recipientAddress = _toController.text;
+        });
+      } else {
+        if (model.sendTicker.toUpperCase() ==
+            tuple.item2.ticker.toUpperCase()) {
+          ref
+              .read(walletsChangeNotifierProvider)
+              .getManager(tuple.item1)
+              .currentReceivingAddress
+              .then((value) {
+            _refundController.text = value;
+            model.refundAddress = _refundController.text;
+          });
+        }
+      }
+    }
+
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    _toController.dispose();
+    _refundController.dispose();
+
+    _toFocusNode.dispose();
+    _refundFocusNode.dispose();
+
+    super.dispose();
+  }
 
   @override
   Widget build(BuildContext context) {
@@ -30,7 +213,243 @@ class DesktopStep2 extends StatelessWidget {
         const SizedBox(
           height: 20,
         ),
-        //
+        Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            Text(
+              "Recipient Wallet",
+              style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+                  color: Theme.of(context)
+                      .extension<StackColors>()!
+                      .textFieldActiveSearchIconRight),
+            ),
+            if (isStackCoin(model.receiveTicker))
+              BlueTextButton(
+                text: "Choose from stack",
+                onTap: selectRecipientAddressFromStack,
+              ),
+          ],
+        ),
+        const SizedBox(
+          height: 4,
+        ),
+        ClipRRect(
+          borderRadius: BorderRadius.circular(
+            Constants.size.circularBorderRadius,
+          ),
+          child: TextField(
+            onTap: () {},
+            key: const Key("recipientExchangeStep2ViewAddressFieldKey"),
+            controller: _toController,
+            readOnly: false,
+            autocorrect: false,
+            enableSuggestions: false,
+            // inputFormatters: <TextInputFormatter>[
+            //   FilteringTextInputFormatter.allow(RegExp("[a-zA-Z0-9]{34}")),
+            // ],
+            toolbarOptions: const ToolbarOptions(
+              copy: false,
+              cut: false,
+              paste: true,
+              selectAll: false,
+            ),
+            focusNode: _toFocusNode,
+            style: STextStyles.field(context),
+            onChanged: (value) {
+              setState(() {});
+            },
+            decoration: standardInputDecoration(
+              "Enter the ${model.receiveTicker.toUpperCase()} payout address",
+              _toFocusNode,
+              context,
+              desktopMed: true,
+            ).copyWith(
+              contentPadding: const EdgeInsets.only(
+                left: 16,
+                top: 6,
+                bottom: 8,
+                right: 5,
+              ),
+              suffixIcon: Padding(
+                padding: _toController.text.isEmpty
+                    ? const EdgeInsets.only(right: 8)
+                    : const EdgeInsets.only(right: 0),
+                child: UnconstrainedBox(
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.spaceAround,
+                    children: [
+                      _toController.text.isNotEmpty
+                          ? TextFieldIconButton(
+                              key: const Key(
+                                  "sendViewClearAddressFieldButtonKey"),
+                              onTap: () {
+                                _toController.text = "";
+                                model.recipientAddress = _toController.text;
+                                setState(() {});
+                              },
+                              child: const XIcon(),
+                            )
+                          : TextFieldIconButton(
+                              key: const Key(
+                                  "sendViewPasteAddressFieldButtonKey"),
+                              onTap: () async {
+                                final ClipboardData? data = await clipboard
+                                    .getData(Clipboard.kTextPlain);
+                                if (data?.text != null &&
+                                    data!.text!.isNotEmpty) {
+                                  final content = data.text!.trim();
+                                  _toController.text = content;
+                                  model.recipientAddress = _toController.text;
+                                  setState(() {});
+                                }
+                              },
+                              child: _toController.text.isEmpty
+                                  ? const ClipboardIcon()
+                                  : const XIcon(),
+                            ),
+                      if (_toController.text.isEmpty)
+                        TextFieldIconButton(
+                          key: const Key("sendViewAddressBookButtonKey"),
+                          onTap: selectRecipientFromAddressBook,
+                          child: const AddressBookIcon(),
+                        ),
+                    ],
+                  ),
+                ),
+              ),
+            ),
+          ),
+        ),
+        const SizedBox(
+          height: 6,
+        ),
+        RoundedWhiteContainer(
+          child: Text(
+            "This is the wallet where your ${model.receiveTicker.toUpperCase()} will be sent to.",
+            style: STextStyles.desktopTextExtraExtraSmall(context),
+          ),
+        ),
+        const SizedBox(
+          height: 24,
+        ),
+        Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            Text(
+              "Refund Wallet (required)",
+              style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+                  color: Theme.of(context)
+                      .extension<StackColors>()!
+                      .textFieldActiveSearchIconRight),
+            ),
+            if (isStackCoin(model.sendTicker))
+              BlueTextButton(
+                text: "Choose from stack",
+                onTap: selectRefundAddressFromStack,
+              ),
+          ],
+        ),
+        const SizedBox(
+          height: 4,
+        ),
+        ClipRRect(
+          borderRadius: BorderRadius.circular(
+            Constants.size.circularBorderRadius,
+          ),
+          child: TextField(
+            key: const Key("refundExchangeStep2ViewAddressFieldKey"),
+            controller: _refundController,
+            readOnly: false,
+            autocorrect: false,
+            enableSuggestions: false,
+            // inputFormatters: <TextInputFormatter>[
+            //   FilteringTextInputFormatter.allow(RegExp("[a-zA-Z0-9]{34}")),
+            // ],
+            toolbarOptions: const ToolbarOptions(
+              copy: false,
+              cut: false,
+              paste: true,
+              selectAll: false,
+            ),
+            focusNode: _refundFocusNode,
+            style: STextStyles.field(context),
+            onChanged: (value) {
+              setState(() {});
+            },
+            decoration: standardInputDecoration(
+              "Enter ${model.sendTicker.toUpperCase()} refund address",
+              _refundFocusNode,
+              context,
+            ).copyWith(
+              contentPadding: const EdgeInsets.only(
+                left: 16,
+                top: 6,
+                bottom: 8,
+                right: 5,
+              ),
+              suffixIcon: Padding(
+                padding: _refundController.text.isEmpty
+                    ? const EdgeInsets.only(right: 16)
+                    : const EdgeInsets.only(right: 0),
+                child: UnconstrainedBox(
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.spaceAround,
+                    children: [
+                      _refundController.text.isNotEmpty
+                          ? TextFieldIconButton(
+                              key: const Key(
+                                  "sendViewClearAddressFieldButtonKey"),
+                              onTap: () {
+                                _refundController.text = "";
+                                model.refundAddress = _refundController.text;
+
+                                setState(() {});
+                              },
+                              child: const XIcon(),
+                            )
+                          : TextFieldIconButton(
+                              key: const Key(
+                                  "sendViewPasteAddressFieldButtonKey"),
+                              onTap: () async {
+                                final ClipboardData? data = await clipboard
+                                    .getData(Clipboard.kTextPlain);
+                                if (data?.text != null &&
+                                    data!.text!.isNotEmpty) {
+                                  final content = data.text!.trim();
+
+                                  _refundController.text = content;
+                                  model.refundAddress = _refundController.text;
+
+                                  setState(() {});
+                                }
+                              },
+                              child: _refundController.text.isEmpty
+                                  ? const ClipboardIcon()
+                                  : const XIcon(),
+                            ),
+                      if (_refundController.text.isEmpty)
+                        TextFieldIconButton(
+                          key: const Key("sendViewAddressBookButtonKey"),
+                          onTap: selectRefundFromAddressBook,
+                          child: const AddressBookIcon(),
+                        ),
+                    ],
+                  ),
+                ),
+              ),
+            ),
+          ),
+        ),
+        const SizedBox(
+          height: 6,
+        ),
+        RoundedWhiteContainer(
+          borderColor: Theme.of(context).extension<StackColors>()!.background,
+          child: Text(
+            "In case something goes wrong during the exchange, we might need a refund address so we can return your coins back to you.",
+            style: STextStyles.desktopTextExtraExtraSmall(context),
+          ),
+        ),
         Padding(
           padding: const EdgeInsets.only(
             top: 20,

From 648c896b9e9a8a38e00faf63762c1bba5c37280d Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 09:49:27 -0600
Subject: [PATCH 066/100] refactor desktop step item

---
 .../subwidgets/desktop_step_1.dart            | 10 ++--
 .../subwidgets/desktop_step_3.dart            | 10 ++--
 .../subwidgets/desktop_step_4.dart            | 10 ++--
 .../subwidgets/desktop_step_item.dart         | 59 +++++++++++++++++++
 .../subwidgets/step_one_item.dart             | 38 ------------
 5 files changed, 74 insertions(+), 53 deletions(-)
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart
 delete mode 100644 lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart

diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
index 1f892dd52..942747ea2 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
 import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
-import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
 import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
@@ -41,7 +41,7 @@ class DesktopStep1 extends ConsumerWidget {
           padding: const EdgeInsets.all(0),
           child: Column(
             children: [
-              StepOneItem(
+              DesktopStepItem(
                 label: "Exchange",
                 value: ref.watch(currentExchangeNameStateProvider.state).state,
               ),
@@ -49,7 +49,7 @@ class DesktopStep1 extends ConsumerWidget {
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              StepOneItem(
+              DesktopStepItem(
                 label: "You send",
                 value:
                     "${model.sendAmount.toStringAsFixed(8)} ${model.sendTicker.toUpperCase()}",
@@ -58,7 +58,7 @@ class DesktopStep1 extends ConsumerWidget {
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              StepOneItem(
+              DesktopStepItem(
                 label: "You receive",
                 value:
                     "~${model.receiveAmount.toStringAsFixed(8)} ${model.receiveTicker.toUpperCase()}",
@@ -67,7 +67,7 @@ class DesktopStep1 extends ConsumerWidget {
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              StepOneItem(
+              DesktopStepItem(
                 label: model.rateType == ExchangeRateType.estimated
                     ? "Estimated rate"
                     : "Fixed rate",
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
index 1e2743ef5..655c3518e 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
@@ -1,5 +1,5 @@
 import 'package:flutter/material.dart';
-import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
@@ -25,7 +25,7 @@ class DesktopStep3 extends StatelessWidget {
           padding: const EdgeInsets.all(0),
           child: Column(
             children: [
-              const StepOneItem(
+              const DesktopStepItem(
                 label: "Exchange",
                 value: "lol",
               ),
@@ -33,7 +33,7 @@ class DesktopStep3 extends StatelessWidget {
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const StepOneItem(
+              const DesktopStepItem(
                 label: "You send",
                 value: "lol",
               ),
@@ -41,7 +41,7 @@ class DesktopStep3 extends StatelessWidget {
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const StepOneItem(
+              const DesktopStepItem(
                 label: "You receive",
                 value: "lol",
               ),
@@ -49,7 +49,7 @@ class DesktopStep3 extends StatelessWidget {
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const StepOneItem(
+              const DesktopStepItem(
                 label: "Rate",
                 value: "lol",
               ),
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
index 8604e7c23..3b3853efb 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
@@ -1,5 +1,5 @@
 import 'package:flutter/material.dart';
-import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
@@ -32,7 +32,7 @@ class DesktopStep4 extends StatelessWidget {
           padding: const EdgeInsets.all(0),
           child: Column(
             children: [
-              const StepOneItem(
+              const DesktopStepItem(
                 label: "Exchange",
                 value: "lol",
               ),
@@ -40,7 +40,7 @@ class DesktopStep4 extends StatelessWidget {
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const StepOneItem(
+              const DesktopStepItem(
                 label: "You send",
                 value: "lol",
               ),
@@ -48,7 +48,7 @@ class DesktopStep4 extends StatelessWidget {
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const StepOneItem(
+              const DesktopStepItem(
                 label: "You receive",
                 value: "lol",
               ),
@@ -56,7 +56,7 @@ class DesktopStep4 extends StatelessWidget {
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const StepOneItem(
+              const DesktopStepItem(
                 label: "Rate",
                 value: "lol",
               ),
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart
new file mode 100644
index 000000000..7c777c2dd
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart
@@ -0,0 +1,59 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
+
+class DesktopStepItem extends StatelessWidget {
+  const DesktopStepItem(
+      {Key? key,
+      required this.label,
+      required this.value,
+      this.padding = const EdgeInsets.all(16),
+      this.vertical = false})
+      : super(key: key);
+
+  final String label;
+  final String value;
+  final EdgeInsets padding;
+  final bool vertical;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: padding,
+      child: ConditionalParent(
+        condition: vertical,
+        builder: (child) => Column(
+          children: [
+            child,
+            const SizedBox(
+              height: 2,
+            ),
+            Text(
+              value,
+              style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+                color: Theme.of(context).extension<StackColors>()!.textDark,
+              ),
+            ),
+          ],
+        ),
+        child: Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            Text(
+              label,
+              style: STextStyles.desktopTextExtraExtraSmall(context),
+            ),
+            if (!vertical)
+              Text(
+                value,
+                style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
+                  color: Theme.of(context).extension<StackColors>()!.textDark,
+                ),
+              ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart
deleted file mode 100644
index 001383a17..000000000
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/step_one_item.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:stackwallet/utilities/text_styles.dart';
-import 'package:stackwallet/utilities/theme/stack_colors.dart';
-
-class StepOneItem extends StatelessWidget {
-  const StepOneItem({
-    Key? key,
-    required this.label,
-    required this.value,
-    this.padding = const EdgeInsets.all(16),
-  }) : super(key: key);
-
-  final String label;
-  final String value;
-  final EdgeInsets padding;
-
-  @override
-  Widget build(BuildContext context) {
-    return Padding(
-      padding: padding,
-      child: Row(
-        mainAxisAlignment: MainAxisAlignment.spaceBetween,
-        children: [
-          Text(
-            label,
-            style: STextStyles.desktopTextExtraExtraSmall(context),
-          ),
-          Text(
-            value,
-            style: STextStyles.desktopTextExtraExtraSmall(context).copyWith(
-              color: Theme.of(context).extension<StackColors>()!.textDark,
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}

From c9e2c4abb7c3fe41f9ea4c7b8152d5e00f597b76 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 10:14:27 -0600
Subject: [PATCH 067/100] desktop trade steps 3 and 4 mostly laid out

---
 .../exchange_step_views/step_4_view.dart      |   1 -
 .../subwidgets/desktop_step_3.dart            | 170 ++++++++++++++++--
 .../subwidgets/desktop_step_4.dart            | 155 ++++++++++++++--
 3 files changed, 295 insertions(+), 31 deletions(-)

diff --git a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart
index 0921f68e0..a8b403dcf 100644
--- a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart
+++ b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart
@@ -18,7 +18,6 @@ import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/clipboard_interface.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
-import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
 import 'package:stackwallet/utilities/format.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
index 655c3518e..65b6ed2b3 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
@@ -1,13 +1,135 @@
+import 'dart:async';
+
 import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
+import 'package:stackwallet/models/exchange/response_objects/trade.dart';
+import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_4_view.dart';
+import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
+import 'package:stackwallet/providers/exchange/current_exchange_name_state_provider.dart';
+import 'package:stackwallet/providers/exchange/exchange_provider.dart';
+import 'package:stackwallet/providers/global/trades_service_provider.dart';
+import 'package:stackwallet/services/exchange/exchange_response.dart';
+import 'package:stackwallet/services/notifications_api.dart';
+import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/custom_loading_overlay.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
+import 'package:stackwallet/widgets/stack_dialog.dart';
 
-class DesktopStep3 extends StatelessWidget {
-  const DesktopStep3({Key? key}) : super(key: key);
+class DesktopStep3 extends ConsumerStatefulWidget {
+  const DesktopStep3({
+    Key? key,
+    required this.model,
+  }) : super(key: key);
+
+  final IncompleteExchangeModel model;
+
+  @override
+  ConsumerState<DesktopStep3> createState() => _DesktopStep3State();
+}
+
+class _DesktopStep3State extends ConsumerState<DesktopStep3> {
+  late final IncompleteExchangeModel model;
+
+  Future<void> createTrade() async {
+    unawaited(
+      showDialog<void>(
+        context: context,
+        barrierDismissible: false,
+        builder: (_) => WillPopScope(
+          onWillPop: () async => false,
+          child: Container(
+            color: Theme.of(context)
+                .extension<StackColors>()!
+                .overlay
+                .withOpacity(0.6),
+            child: const CustomLoadingOverlay(
+              message: "Creating a trade",
+              eventBus: null,
+            ),
+          ),
+        ),
+      ),
+    );
+
+    final ExchangeResponse<Trade> response =
+        await ref.read(exchangeProvider).createTrade(
+              from: model.sendTicker,
+              to: model.receiveTicker,
+              fixedRate: model.rateType != ExchangeRateType.estimated,
+              amount: model.reversed ? model.receiveAmount : model.sendAmount,
+              addressTo: model.recipientAddress!,
+              extraId: null,
+              addressRefund: model.refundAddress!,
+              refundExtraId: "",
+              rateId: model.rateId,
+              reversed: model.reversed,
+            );
+
+    if (response.value == null) {
+      if (mounted) {
+        Navigator.of(context).pop();
+      }
+
+      unawaited(showDialog<void>(
+        context: context,
+        barrierDismissible: true,
+        builder: (_) => StackDialog(
+          title: "Failed to create trade",
+          message: response.exception?.toString(),
+        ),
+      ));
+      return;
+    }
+
+    // save trade to hive
+    await ref.read(tradesServiceProvider).add(
+          trade: response.value!,
+          shouldNotifyListeners: true,
+        );
+
+    String status = response.value!.status;
+
+    model.trade = response.value!;
+
+    // extra info if status is waiting
+    if (status == "Waiting") {
+      status += " for deposit";
+    }
+
+    if (mounted) {
+      Navigator.of(context).pop();
+    }
+
+    unawaited(NotificationApi.showNotification(
+      changeNowId: model.trade!.tradeId,
+      title: status,
+      body: "Trade ID ${model.trade!.tradeId}",
+      walletId: "",
+      iconAssetName: Assets.svg.arrowRotate,
+      date: model.trade!.timestamp,
+      shouldWatchForUpdates: true,
+      coinName: "coinName",
+    ));
+
+    if (mounted) {
+      unawaited(Navigator.of(context).pushNamed(
+        Step4View.routeName,
+        arguments: model,
+      ));
+    }
+  }
+
+  @override
+  void initState() {
+    model = widget.model;
+    super.initState();
+  }
 
   @override
   Widget build(BuildContext context) {
@@ -25,33 +147,55 @@ class DesktopStep3 extends StatelessWidget {
           padding: const EdgeInsets.all(0),
           child: Column(
             children: [
-              const DesktopStepItem(
+              DesktopStepItem(
                 label: "Exchange",
-                value: "lol",
+                value: ref.watch(currentExchangeNameStateProvider.state).state,
               ),
               Container(
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const DesktopStepItem(
+              DesktopStepItem(
                 label: "You send",
-                value: "lol",
+                value:
+                    "${model.sendAmount.toStringAsFixed(8)} ${model.sendTicker.toUpperCase()}",
               ),
               Container(
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const DesktopStepItem(
+              DesktopStepItem(
                 label: "You receive",
-                value: "lol",
+                value:
+                    "~${model.receiveAmount.toStringAsFixed(8)} ${model.receiveTicker.toUpperCase()}",
               ),
               Container(
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const DesktopStepItem(
-                label: "Rate",
-                value: "lol",
+              DesktopStepItem(
+                label: model.rateType == ExchangeRateType.estimated
+                    ? "Estimated rate"
+                    : "Fixed rate",
+                value: model.rateInfo,
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              DesktopStepItem(
+                vertical: true,
+                label: "Recipient ${model.receiveTicker.toUpperCase()} address",
+                value: model.recipientAddress!,
+              ),
+              Container(
+                height: 1,
+                color: Theme.of(context).extension<StackColors>()!.background,
+              ),
+              DesktopStepItem(
+                vertical: true,
+                label: "Refund ${model.sendTicker.toUpperCase()} address",
+                value: model.refundAddress!,
               ),
             ],
           ),
@@ -77,9 +221,7 @@ class DesktopStep3 extends StatelessWidget {
                 child: PrimaryButton(
                   label: "Confirm",
                   buttonHeight: ButtonHeight.l,
-                  onPressed: () {
-                    // todo
-                  },
+                  onPressed: createTrade,
                 ),
               ),
             ],
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
index 3b3853efb..ba9838086 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
@@ -1,64 +1,187 @@
+import 'dart:async';
+
 import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
+import 'package:stackwallet/providers/providers.dart';
+import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/rounded_container.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 
-class DesktopStep4 extends StatelessWidget {
-  const DesktopStep4({Key? key}) : super(key: key);
+class DesktopStep4 extends ConsumerStatefulWidget {
+  const DesktopStep4({
+    Key? key,
+    required this.model,
+  }) : super(key: key);
+
+  final IncompleteExchangeModel model;
+
+  @override
+  ConsumerState<DesktopStep4> createState() => _DesktopStep4State();
+}
+
+class _DesktopStep4State extends ConsumerState<DesktopStep4> {
+  late final IncompleteExchangeModel model;
+
+  String _statusString = "New";
+
+  Timer? _statusTimer;
+
+  bool _isWalletCoinAndHasWallet(String ticker) {
+    try {
+      final coin = coinFromTickerCaseInsensitive(ticker);
+      return ref
+          .read(walletsChangeNotifierProvider)
+          .managers
+          .where((element) => element.coin == coin)
+          .isNotEmpty;
+    } catch (_) {
+      return false;
+    }
+  }
+
+  Future<void> _updateStatus() async {
+    final statusResponse =
+        await ref.read(exchangeProvider).updateTrade(model.trade!);
+    String status = "Waiting";
+    if (statusResponse.value != null) {
+      status = statusResponse.value!.status;
+    }
+
+    // extra info if status is waiting
+    if (status == "Waiting") {
+      status += " for deposit";
+    }
+
+    if (mounted) {
+      setState(() {
+        _statusString = status;
+      });
+    }
+  }
+
+  @override
+  void initState() {
+    model = widget.model;
+
+    _statusTimer = Timer.periodic(const Duration(seconds: 60), (_) {
+      _updateStatus();
+    });
+
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    _statusTimer?.cancel();
+    _statusTimer = null;
+    super.dispose();
+  }
 
   @override
   Widget build(BuildContext context) {
     return Column(
       children: [
         Text(
-          "Confirm amount",
+          "Send ${model.sendTicker.toUpperCase()} to the address below",
           style: STextStyles.desktopTextMedium(context),
         ),
         const SizedBox(
           height: 8,
         ),
         Text(
-          "Network fees and other exchange charges are included in the rate.",
+          "Send ${model.sendTicker.toUpperCase()} to the address below. Once it is received, ${model.trade!.exchangeName} will send the ${model.receiveTicker.toUpperCase()} to the recipient address you provided. You can find this trade details and check its status in the list of trades.",
           style: STextStyles.desktopTextExtraExtraSmall(context),
         ),
         const SizedBox(
           height: 20,
         ),
+        RoundedContainer(
+          color: Theme.of(context).extension<StackColors>()!.warningBackground,
+          child: RichText(
+            text: TextSpan(
+              text:
+                  "You must send at least ${model.sendAmount.toString()} ${model.sendTicker}. ",
+              style: STextStyles.label700(context).copyWith(
+                color: Theme.of(context)
+                    .extension<StackColors>()!
+                    .warningForeground,
+                fontSize: 14,
+              ),
+              children: [
+                TextSpan(
+                  text:
+                      "If you send less than ${model.sendAmount.toString()} ${model.sendTicker}, your transaction may not be converted and it may not be refunded.",
+                  style: STextStyles.label(context).copyWith(
+                    color: Theme.of(context)
+                        .extension<StackColors>()!
+                        .warningForeground,
+                    fontSize: 14,
+                  ),
+                ),
+              ],
+            ),
+          ),
+        ),
+        const SizedBox(
+          height: 20,
+        ),
         RoundedWhiteContainer(
           borderColor: Theme.of(context).extension<StackColors>()!.background,
           padding: const EdgeInsets.all(0),
           child: Column(
             children: [
-              const DesktopStepItem(
-                label: "Exchange",
-                value: "lol",
+              DesktopStepItem(
+                vertical: true,
+                label: "Send ${model.sendTicker.toUpperCase()} to this address",
+                value: model.trade!.payInAddress,
               ),
               Container(
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const DesktopStepItem(
-                label: "You send",
-                value: "lol",
+              DesktopStepItem(
+                label: "Amount",
+                value:
+                    "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}",
               ),
               Container(
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const DesktopStepItem(
-                label: "You receive",
-                value: "lol",
+              DesktopStepItem(
+                label: "Trade ID",
+                value: model.trade!.tradeId,
               ),
               Container(
                 height: 1,
                 color: Theme.of(context).extension<StackColors>()!.background,
               ),
-              const DesktopStepItem(
-                label: "Rate",
-                value: "lol",
+              Padding(
+                padding: const EdgeInsets.all(16),
+                child: Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  children: [
+                    Text(
+                      "Status",
+                      style: STextStyles.desktopTextExtraExtraSmall(context),
+                    ),
+                    Text(
+                      _statusString,
+                      style: STextStyles.desktopTextExtraExtraSmall(context)
+                          .copyWith(
+                        color: Theme.of(context)
+                            .extension<StackColors>()!
+                            .colorForStatus(_statusString),
+                      ),
+                    ),
+                  ],
+                ),
               ),
             ],
           ),

From 78186358b9de2fc28b989575e1d6bee1c62d1f38 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Mon, 21 Nov 2022 10:50:53 -0700
Subject: [PATCH 068/100] WIP: wallet will be deleted dialog

---
 .../sub_widgets/delete_wallet_keys_popup.dart | 195 ++++++++++++++++++
 .../desktop_attention_delete_wallet.dart      | 122 +++++++++++
 .../desktop_delete_wallet_dialog.dart         |  90 +-------
 lib/route_generator.dart                      |  47 +++++
 4 files changed, 369 insertions(+), 85 deletions(-)
 create mode 100644 lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
 create mode 100644 lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
new file mode 100644
index 000000000..5f46e0f2f
--- /dev/null
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
@@ -0,0 +1,195 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+
+class DeleteWalletKeysPopup extends ConsumerStatefulWidget {
+  const DeleteWalletKeysPopup({
+    Key? key,
+    required this.walletId,
+    required this.words,
+  }) : super(key: key);
+
+  final String walletId;
+  final List<String> words;
+
+  static const String routeName = "/desktopDeleteWalletKeysPopup";
+
+  @override
+  ConsumerState<DeleteWalletKeysPopup> createState() =>
+      _DeleteWalletKeysPopup();
+}
+
+class _DeleteWalletKeysPopup extends ConsumerState<DeleteWalletKeysPopup> {
+  @override
+  Widget build(BuildContext context) {
+    return DesktopDialog(
+      maxWidth: 614,
+      maxHeight: double.infinity,
+      child: Column(
+        children: [
+          Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: [
+              Padding(
+                padding: const EdgeInsets.only(
+                  left: 32,
+                ),
+                child: Text(
+                  "Wallet keys",
+                  style: STextStyles.desktopH3(context),
+                ),
+              ),
+              DesktopDialogCloseButton(
+                onPressedOverride: () {
+                  int count = 0;
+                  Navigator.of(context).popUntil((_) => count++ >= 2);
+                },
+              ),
+            ],
+          ),
+          const SizedBox(
+            height: 28,
+          ),
+          Text(
+            "Recovery phrase",
+            style: STextStyles.desktopTextMedium(context),
+          ),
+          const SizedBox(
+            height: 8,
+          ),
+          Center(
+            child: Padding(
+              padding: const EdgeInsets.symmetric(
+                horizontal: 32,
+              ),
+              child: Text(
+                "Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.",
+                style: STextStyles.desktopTextExtraExtraSmall(context),
+                textAlign: TextAlign.center,
+              ),
+            ),
+          ),
+          const SizedBox(
+            height: 24,
+          ),
+          Padding(
+            padding: const EdgeInsets.symmetric(
+              horizontal: 32,
+            ),
+            child: MnemonicTable(
+              words: widget.words,
+              isDesktop: true,
+              itemBorderColor: Theme.of(context)
+                  .extension<StackColors>()!
+                  .buttonBackSecondary,
+            ),
+          ),
+          const SizedBox(
+            height: 24,
+          ),
+          Padding(
+            padding: const EdgeInsets.symmetric(
+              horizontal: 32,
+            ),
+            child: Row(
+              children: [
+                Expanded(
+                  child: PrimaryButton(
+                    label: "Continue",
+                    onPressed: () async {
+                      int count = 0;
+                      Navigator.of(context).popUntil((_) => count++ >= 2);
+
+                      unawaited(
+                        showDialog(
+                            context: context,
+                            builder: (context) {
+                              return DesktopDialog(
+                                child: Column(
+                                  children: [
+                                    Row(
+                                      mainAxisAlignment: MainAxisAlignment.end,
+                                      children: [
+                                        DesktopDialogCloseButton(
+                                          onPressedOverride: () {
+                                            int count = 0;
+                                            Navigator.of(context)
+                                                .popUntil((_) => count++ >= 2);
+                                          },
+                                        ),
+                                      ],
+                                    ),
+                                    Column(
+                                      children: [
+                                        Text(
+                                          "Thanks! "
+                                          "\n\nYour wallet will be deleted.",
+                                          style: STextStyles.desktopH2(context),
+                                        ),
+                                        const SizedBox(height: 20),
+                                        Row(
+                                          mainAxisAlignment:
+                                              MainAxisAlignment.center,
+                                          children: [
+                                            SecondaryButton(
+                                                width: 250,
+                                                buttonHeight: ButtonHeight.xl,
+                                                label: "Cancel",
+                                                onPressed: () {
+                                                  int count = 0;
+                                                  Navigator.of(context)
+                                                      .popUntil(
+                                                          (_) => count++ >= 2);
+                                                }),
+                                            const SizedBox(width: 16),
+                                            PrimaryButton(
+                                                width: 250,
+                                                buttonHeight: ButtonHeight.xl,
+                                                label: "Continue",
+                                                onPressed: () async {
+                                                  // final walletsInstance =
+                                                  // ref.read(walletsChangeNotifierProvider);
+                                                  // await ref
+                                                  //     .read(walletsServiceChangeNotifierProvider)
+                                                  //     .deleteWallet(walletId, true);
+                                                  //
+                                                  // if (mounted) {
+                                                  //   Navigator.of(context).popUntil(
+                                                  //       ModalRoute.withName(HomeView.routeName));
+                                                  // }
+
+                                                  // // wait for widget tree to dispose of any widgets watching the manager
+                                                  // await Future<void>.delayed(const Duration(seconds: 1));
+                                                  // walletsInstance.removeWallet(walletId: walletId);
+                                                }),
+                                          ],
+                                        )
+                                      ],
+                                    ),
+                                  ],
+                                ),
+                              );
+                            }),
+                      );
+                    },
+                  ),
+                ),
+              ],
+            ),
+          ),
+          const SizedBox(
+            height: 32,
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart
new file mode 100644
index 000000000..30546f60b
--- /dev/null
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart
@@ -0,0 +1,122 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/rounded_container.dart';
+import 'package:tuple/tuple.dart';
+
+import 'delete_wallet_keys_popup.dart';
+
+class DesktopAttentionDeleteWallet extends ConsumerStatefulWidget {
+  const DesktopAttentionDeleteWallet({
+    Key? key,
+    required this.walletId,
+  }) : super(key: key);
+
+  final String walletId;
+
+  static const String routeName = "/desktopAttentionDeleteWallet";
+
+  @override
+  ConsumerState<DesktopAttentionDeleteWallet> createState() =>
+      _DesktopAttentionDeleteWallet();
+}
+
+class _DesktopAttentionDeleteWallet
+    extends ConsumerState<DesktopAttentionDeleteWallet> {
+  @override
+  Widget build(BuildContext context) {
+    return DesktopDialog(
+      maxWidth: 610,
+      maxHeight: 530,
+      child: Column(
+        children: [
+          Row(
+            mainAxisAlignment: MainAxisAlignment.end,
+            children: [
+              DesktopDialogCloseButton(
+                onPressedOverride: () {
+                  int count = 0;
+                  Navigator.of(context).popUntil((_) => count++ >= 2);
+                },
+              ),
+            ],
+          ),
+          Padding(
+            padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 26),
+            child: Column(
+              children: [
+                Text(
+                  "Attention!",
+                  style: STextStyles.desktopH2(context),
+                ),
+                const SizedBox(
+                  height: 16,
+                ),
+                RoundedContainer(
+                  color: Theme.of(context)
+                      .extension<StackColors>()!
+                      .snackBarBackError,
+                  child: Padding(
+                    padding: const EdgeInsets.all(10.0),
+                    child: Text(
+                      "You are going to permanently delete you wallet.\n\nIf you delete your wallet, "
+                      "the only way you can have access to your funds is by using your backup key."
+                      "\n\nStack Wallet does not keep nor is able to restore your backup key or your wallet."
+                      "\n\nPLEASE SAVE YOUR BACKUP KEY.",
+                      style: STextStyles.desktopTextExtraExtraSmall(context)
+                          .copyWith(
+                        color: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textDark3,
+                      ),
+                    ),
+                  ),
+                ),
+                const SizedBox(height: 30),
+                Row(
+                  mainAxisAlignment: MainAxisAlignment.center,
+                  children: [
+                    SecondaryButton(
+                      width: 250,
+                      buttonHeight: ButtonHeight.xl,
+                      label: "Cancel",
+                      onPressed: () {
+                        int count = 0;
+                        Navigator.of(context).popUntil((_) => count++ >= 2);
+                      },
+                    ),
+                    const SizedBox(width: 16),
+                    PrimaryButton(
+                      width: 250,
+                      buttonHeight: ButtonHeight.xl,
+                      label: "View Backup Key",
+                      onPressed: () async {
+                        final words = await ref
+                            .read(walletsChangeNotifierProvider)
+                            .getManager(widget.walletId)
+                            .mnemonic;
+
+                        await Navigator.of(context)
+                            .pushNamed(DeleteWalletKeysPopup.routeName,
+                                arguments: Tuple2(
+                                  widget.walletId,
+                                  words,
+                                ));
+                      },
+                    ),
+                  ],
+                )
+              ],
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
index e2ab4fa86..087629673 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/svg.dart';
 import 'package:stackwallet/notifications/show_flush_bar.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
@@ -12,7 +13,6 @@ import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
-import 'package:stackwallet/widgets/rounded_container.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 
 import '../../../../../providers/desktop/storage_crypto_handler_provider.dart';
@@ -41,89 +41,6 @@ class _DesktopDeleteWalletDialog
   bool hidePassword = true;
   bool _continueEnabled = false;
 
-  Future<void> attentionDelete() async {
-    await showDialog<dynamic>(
-      context: context,
-      useSafeArea: false,
-      barrierDismissible: true,
-      builder: (context) => DesktopDialog(
-        maxWidth: 610,
-        maxHeight: 530,
-        child: Column(
-          children: [
-            Row(
-              mainAxisAlignment: MainAxisAlignment.end,
-              children: [
-                DesktopDialogCloseButton(
-                  onPressedOverride: () {
-                    int count = 0;
-                    Navigator.of(context).popUntil((_) => count++ >= 2);
-                  },
-                ),
-              ],
-            ),
-            Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 26),
-              child: Column(
-                children: [
-                  Text(
-                    "Attention!",
-                    style: STextStyles.desktopH2(context),
-                  ),
-                  const SizedBox(
-                    height: 16,
-                  ),
-                  RoundedContainer(
-                    color: Theme.of(context)
-                        .extension<StackColors>()!
-                        .snackBarBackError,
-                    child: Padding(
-                      padding: const EdgeInsets.all(10.0),
-                      child: Text(
-                        "You are going to permanently delete you wallet.\n\nIf you delete your wallet, "
-                        "the only way you can have access to your funds is by using your backup key."
-                        "\n\nStack Wallet does not keep nor is able to restore your backup key or your wallet."
-                        "\n\nPLEASE SAVE YOUR BACKUP KEY.",
-                        style: STextStyles.desktopTextExtraExtraSmall(context)
-                            .copyWith(
-                          color: Theme.of(context)
-                              .extension<StackColors>()!
-                              .textDark3,
-                        ),
-                      ),
-                    ),
-                  ),
-                  const SizedBox(height: 30),
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.center,
-                    children: [
-                      SecondaryButton(
-                        width: 250,
-                        buttonHeight: ButtonHeight.xl,
-                        label: "Cancel",
-                        onPressed: () {
-                          int count = 0;
-                          Navigator.of(context).popUntil((_) => count++ >= 2);
-                        },
-                      ),
-                      const SizedBox(width: 16),
-                      PrimaryButton(
-                        width: 250,
-                        buttonHeight: ButtonHeight.xl,
-                        label: "View Backup Key",
-                        onPressed: () {},
-                      ),
-                    ],
-                  )
-                ],
-              ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-
   @override
   void initState() {
     passwordController = TextEditingController();
@@ -273,7 +190,10 @@ class _DesktopDeleteWalletDialog
                                 if (mounted) {
                                   Navigator.of(context).pop();
 
-                                  attentionDelete();
+                                  await Navigator.of(context).pushNamed(
+                                    DesktopAttentionDeleteWallet.routeName,
+                                    arguments: widget.walletId,
+                                  );
                                 }
                               } else {
                                 unawaited(
diff --git a/lib/route_generator.dart b/lib/route_generator.dart
index 77b5e7d11..cbc4cb343 100644
--- a/lib/route_generator.dart
+++ b/lib/route_generator.dart
@@ -92,6 +92,8 @@ import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/desktop_settings_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_stack_view.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/qr_code_desktop_popup_content.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart';
@@ -1193,6 +1195,51 @@ class RouteGenerator {
         }
         return _routeError("${settings.name} invalid args: ${args.toString()}");
 
+      case DesktopAttentionDeleteWallet.routeName:
+        if (args is String) {
+          return FadePageRoute(
+            DesktopAttentionDeleteWallet(
+              walletId: args,
+            ),
+            RouteSettings(
+              name: settings.name,
+            ),
+          );
+          // return getRoute(
+          //   shouldUseMaterialRoute: useMaterialPageRoute,
+          //   builder: (_) => WalletKeysDesktopPopup(
+          //     words: args,
+          //   ),
+          //   settings: RouteSettings(
+          //     name: settings.name,
+          //   ),
+          // );
+        }
+        return _routeError("${settings.name} invalid args: ${args.toString()}");
+
+      case DeleteWalletKeysPopup.routeName:
+        if (args is Tuple2<String, List<String>>) {
+          return FadePageRoute(
+            DeleteWalletKeysPopup(
+              walletId: args.item1,
+              words: args.item2,
+            ),
+            RouteSettings(
+              name: settings.name,
+            ),
+          );
+          // return getRoute(
+          //   shouldUseMaterialRoute: useMaterialPageRoute,
+          //   builder: (_) => WalletKeysDesktopPopup(
+          //     words: args,
+          //   ),
+          //   settings: RouteSettings(
+          //     name: settings.name,
+          //   ),
+          // );
+        }
+        return _routeError("${settings.name} invalid args: ${args.toString()}");
+
       case QRCodeDesktopPopupContent.routeName:
         if (args is String) {
           return FadePageRoute(

From 5c7cb8a3c5d033dab7f0614ce090f5d783d53b77 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Mon, 21 Nov 2022 12:18:35 -0700
Subject: [PATCH 069/100] WIP: unmounted widget

---
 .../sub_widgets/delete_wallet_keys_popup.dart | 67 +++++++++++++++----
 1 file changed, 53 insertions(+), 14 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
index 5f46e0f2f..f70c2eadf 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
@@ -3,6 +3,9 @@ import 'dart:async';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_stack_view.dart';
+import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/providers/global/wallets_service_provider.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
@@ -28,6 +31,15 @@ class DeleteWalletKeysPopup extends ConsumerStatefulWidget {
 }
 
 class _DeleteWalletKeysPopup extends ConsumerState<DeleteWalletKeysPopup> {
+  late final String _walletId;
+
+  @override
+  void initState() {
+    _walletId = widget.walletId;
+
+    super.initState();
+  }
+
   @override
   Widget build(BuildContext context) {
     return DesktopDialog(
@@ -113,6 +125,7 @@ class _DeleteWalletKeysPopup extends ConsumerState<DeleteWalletKeysPopup> {
                             context: context,
                             builder: (context) {
                               return DesktopDialog(
+                                maxHeight: 350,
                                 child: Column(
                                   children: [
                                     Row(
@@ -128,13 +141,16 @@ class _DeleteWalletKeysPopup extends ConsumerState<DeleteWalletKeysPopup> {
                                       ],
                                     ),
                                     Column(
+                                      crossAxisAlignment:
+                                          CrossAxisAlignment.center,
                                       children: [
                                         Text(
                                           "Thanks! "
                                           "\n\nYour wallet will be deleted.",
                                           style: STextStyles.desktopH2(context),
+                                          textAlign: TextAlign.center,
                                         ),
-                                        const SizedBox(height: 20),
+                                        const SizedBox(height: 50),
                                         Row(
                                           mainAxisAlignment:
                                               MainAxisAlignment.center,
@@ -155,20 +171,43 @@ class _DeleteWalletKeysPopup extends ConsumerState<DeleteWalletKeysPopup> {
                                                 buttonHeight: ButtonHeight.xl,
                                                 label: "Continue",
                                                 onPressed: () async {
-                                                  // final walletsInstance =
-                                                  // ref.read(walletsChangeNotifierProvider);
-                                                  // await ref
-                                                  //     .read(walletsServiceChangeNotifierProvider)
-                                                  //     .deleteWallet(walletId, true);
-                                                  //
-                                                  // if (mounted) {
-                                                  //   Navigator.of(context).popUntil(
-                                                  //       ModalRoute.withName(HomeView.routeName));
-                                                  // }
+                                                  // int count = 0;
+                                                  // Navigator.of(context)
+                                                  //     .popUntil(
+                                                  //         (_) => count++ >= 2);
 
-                                                  // // wait for widget tree to dispose of any widgets watching the manager
-                                                  // await Future<void>.delayed(const Duration(seconds: 1));
-                                                  // walletsInstance.removeWallet(walletId: walletId);
+                                                  final walletsInstance = ref.read(
+                                                      walletsChangeNotifierProvider);
+                                                  final manager = ref
+                                                      .read(
+                                                          walletsChangeNotifierProvider)
+                                                      .getManager(_walletId);
+
+                                                  final _managerWalletId =
+                                                      manager.walletId;
+
+                                                  await ref
+                                                      .read(
+                                                          walletsServiceChangeNotifierProvider)
+                                                      .deleteWallet(
+                                                          manager.walletName,
+                                                          true);
+
+                                                  if (mounted) {
+                                                    Navigator.of(context)
+                                                        .popUntil(
+                                                            ModalRoute.withName(
+                                                                MyStackView
+                                                                    .routeName));
+                                                  }
+
+                                                  // wait for widget tree to dispose of any widgets watching the manager
+                                                  await Future<void>.delayed(
+                                                      const Duration(
+                                                          seconds: 1));
+                                                  walletsInstance.removeWallet(
+                                                      walletId:
+                                                          _managerWalletId);
                                                 }),
                                           ],
                                         )

From d06c4862b1685b19f48686b8c3c27a7542fedd16 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 11:21:44 -0600
Subject: [PATCH 070/100] desktop exchange coin selection ui

---
 .../fixed_rate_pair_coin_selection_view.dart  | 319 +++++++++---------
 ...floating_rate_currency_selection_view.dart | 317 ++++++++---------
 lib/pages/exchange_view/exchange_form.dart    | 143 +++++++-
 3 files changed, 459 insertions(+), 320 deletions(-)

diff --git a/lib/pages/exchange_view/exchange_coin_selection/fixed_rate_pair_coin_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/fixed_rate_pair_coin_selection_view.dart
index 80bdcda62..779d99306 100644
--- a/lib/pages/exchange_view/exchange_coin_selection/fixed_rate_pair_coin_selection_view.dart
+++ b/lib/pages/exchange_view/exchange_coin_selection/fixed_rate_pair_coin_selection_view.dart
@@ -8,6 +8,8 @@ import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
 import 'package:stackwallet/widgets/loading_indicator.dart';
@@ -16,8 +18,6 @@ import 'package:stackwallet/widgets/stack_text_field.dart';
 import 'package:stackwallet/widgets/textfield_icon_button.dart';
 import 'package:tuple/tuple.dart';
 
-import 'package:stackwallet/utilities/util.dart';
-
 class FixedRateMarketPairCoinSelectionView extends ConsumerStatefulWidget {
   const FixedRateMarketPairCoinSelectionView({
     Key? key,
@@ -120,95 +120,106 @@ class _FixedRateMarketPairCoinSelectionViewState
 
   @override
   Widget build(BuildContext context) {
-    return Scaffold(
-      backgroundColor: Theme.of(context).extension<StackColors>()!.background,
-      appBar: AppBar(
-        leading: AppBarBackButton(
-          onPressed: () async {
-            if (FocusScope.of(context).hasFocus) {
-              FocusScope.of(context).unfocus();
-              await Future<void>.delayed(const Duration(milliseconds: 50));
-            }
-            if (mounted) {
-              Navigator.of(context).pop();
-            }
-          },
-        ),
-        title: Text(
-          "Choose a coin to exchange",
-          style: STextStyles.pageTitleH2(context),
-        ),
-      ),
-      body: Padding(
-        padding: const EdgeInsets.symmetric(
-          horizontal: 16,
-        ),
-        child: Column(
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
+    final isDesktop = Util.isDesktop;
+    return ConditionalParent(
+      condition: !isDesktop,
+      builder: (child) {
+        return Scaffold(
+          backgroundColor:
+              Theme.of(context).extension<StackColors>()!.background,
+          appBar: AppBar(
+            leading: AppBarBackButton(
+              onPressed: () async {
+                if (FocusScope.of(context).hasFocus) {
+                  FocusScope.of(context).unfocus();
+                  await Future<void>.delayed(const Duration(milliseconds: 50));
+                }
+                if (mounted) {
+                  Navigator.of(context).pop();
+                }
+              },
+            ),
+            title: Text(
+              "Choose a coin to exchange",
+              style: STextStyles.pageTitleH2(context),
+            ),
+          ),
+          body: Padding(
+            padding: const EdgeInsets.symmetric(
+              horizontal: 16,
+            ),
+            child: child,
+          ),
+        );
+      },
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          if (!isDesktop)
             const SizedBox(
               height: 16,
             ),
-            ClipRRect(
-              borderRadius: BorderRadius.circular(
-                Constants.size.circularBorderRadius,
-              ),
-              child: TextField(
-                autocorrect: Util.isDesktop ? false : true,
-                enableSuggestions: Util.isDesktop ? false : true,
-                controller: _searchController,
-                focusNode: _searchFocusNode,
-                onChanged: filter,
-                style: STextStyles.field(context),
-                decoration: standardInputDecoration(
-                  "Search",
-                  _searchFocusNode,
-                  context,
-                ).copyWith(
-                  prefixIcon: Padding(
-                    padding: const EdgeInsets.symmetric(
-                      horizontal: 10,
-                      vertical: 16,
-                    ),
-                    child: SvgPicture.asset(
-                      Assets.svg.search,
-                      width: 16,
-                      height: 16,
-                    ),
+          ClipRRect(
+            borderRadius: BorderRadius.circular(
+              Constants.size.circularBorderRadius,
+            ),
+            child: TextField(
+              autocorrect: Util.isDesktop ? false : true,
+              enableSuggestions: Util.isDesktop ? false : true,
+              controller: _searchController,
+              focusNode: _searchFocusNode,
+              onChanged: filter,
+              style: STextStyles.field(context),
+              decoration: standardInputDecoration(
+                "Search",
+                _searchFocusNode,
+                context,
+              ).copyWith(
+                prefixIcon: Padding(
+                  padding: const EdgeInsets.symmetric(
+                    horizontal: 10,
+                    vertical: 16,
+                  ),
+                  child: SvgPicture.asset(
+                    Assets.svg.search,
+                    width: 16,
+                    height: 16,
                   ),
-                  suffixIcon: _searchController.text.isNotEmpty
-                      ? Padding(
-                          padding: const EdgeInsets.only(right: 0),
-                          child: UnconstrainedBox(
-                            child: Row(
-                              children: [
-                                TextFieldIconButton(
-                                  child: const XIcon(),
-                                  onTap: () async {
-                                    setState(() {
-                                      _searchController.text = "";
-                                    });
-                                  },
-                                ),
-                              ],
-                            ),
-                          ),
-                        )
-                      : null,
                 ),
+                suffixIcon: _searchController.text.isNotEmpty
+                    ? Padding(
+                        padding: const EdgeInsets.only(right: 0),
+                        child: UnconstrainedBox(
+                          child: Row(
+                            children: [
+                              TextFieldIconButton(
+                                child: const XIcon(),
+                                onTap: () async {
+                                  setState(() {
+                                    _searchController.text = "";
+                                  });
+                                },
+                              ),
+                            ],
+                          ),
+                        ),
+                      )
+                    : null,
               ),
             ),
-            const SizedBox(
-              height: 10,
-            ),
-            Text(
-              "Popular coins",
-              style: STextStyles.smallMed12(context),
-            ),
-            const SizedBox(
-              height: 12,
-            ),
-            Builder(builder: (context) {
+          ),
+          const SizedBox(
+            height: 10,
+          ),
+          Text(
+            "Popular coins",
+            style: STextStyles.smallMed12(context),
+          ),
+          const SizedBox(
+            height: 12,
+          ),
+          Flexible(
+            child: Builder(builder: (context) {
               final items = _markets
                   .where((e) => Coin.values
                       .where((coin) =>
@@ -221,6 +232,7 @@ class _FixedRateMarketPairCoinSelectionViewState
                 padding: const EdgeInsets.all(0),
                 child: ListView.builder(
                   shrinkWrap: true,
+                  primary: isDesktop ? false : null,
                   itemCount: items.length,
                   itemBuilder: (builderContext, index) {
                     final String ticker =
@@ -282,84 +294,85 @@ class _FixedRateMarketPairCoinSelectionViewState
                 ),
               );
             }),
-            const SizedBox(
-              height: 20,
-            ),
-            Text(
-              "All coins",
-              style: STextStyles.smallMed12(context),
-            ),
-            const SizedBox(
-              height: 12,
-            ),
-            Flexible(
-              child: RoundedWhiteContainer(
-                padding: const EdgeInsets.all(0),
-                child: ListView.builder(
-                  shrinkWrap: true,
-                  itemCount: _markets.length,
-                  itemBuilder: (builderContext, index) {
-                    final String ticker =
-                        isFrom ? _markets[index].from : _markets[index].to;
+          ),
+          const SizedBox(
+            height: 20,
+          ),
+          Text(
+            "All coins",
+            style: STextStyles.smallMed12(context),
+          ),
+          const SizedBox(
+            height: 12,
+          ),
+          Flexible(
+            child: RoundedWhiteContainer(
+              padding: const EdgeInsets.all(0),
+              child: ListView.builder(
+                shrinkWrap: true,
+                primary: isDesktop ? false : null,
+                itemCount: _markets.length,
+                itemBuilder: (builderContext, index) {
+                  final String ticker =
+                      isFrom ? _markets[index].from : _markets[index].to;
 
-                    final tuple = _imageUrlAndNameFor(ticker);
-                    return Padding(
-                      padding: const EdgeInsets.symmetric(vertical: 4),
-                      child: GestureDetector(
-                        onTap: () {
-                          Navigator.of(context).pop(ticker);
-                        },
-                        child: RoundedWhiteContainer(
-                          child: Row(
-                            children: [
-                              SizedBox(
+                  final tuple = _imageUrlAndNameFor(ticker);
+                  return Padding(
+                    padding: const EdgeInsets.symmetric(vertical: 4),
+                    child: GestureDetector(
+                      onTap: () {
+                        Navigator.of(context).pop(ticker);
+                      },
+                      child: RoundedWhiteContainer(
+                        child: Row(
+                          children: [
+                            SizedBox(
+                              width: 24,
+                              height: 24,
+                              child: SvgPicture.network(
+                                tuple.item1,
                                 width: 24,
                                 height: 24,
-                                child: SvgPicture.network(
-                                  tuple.item1,
-                                  width: 24,
-                                  height: 24,
-                                  placeholderBuilder: (_) =>
-                                      const LoadingIndicator(),
-                                ),
+                                placeholderBuilder: (_) =>
+                                    const LoadingIndicator(),
                               ),
-                              const SizedBox(
-                                width: 10,
+                            ),
+                            const SizedBox(
+                              width: 10,
+                            ),
+                            Expanded(
+                              child: Column(
+                                crossAxisAlignment: CrossAxisAlignment.start,
+                                children: [
+                                  Text(
+                                    tuple.item2,
+                                    style: STextStyles.largeMedium14(context),
+                                  ),
+                                  const SizedBox(
+                                    height: 2,
+                                  ),
+                                  Text(
+                                    ticker.toUpperCase(),
+                                    style: STextStyles.smallMed12(context)
+                                        .copyWith(
+                                      color: Theme.of(context)
+                                          .extension<StackColors>()!
+                                          .textSubtitle1,
+                                    ),
+                                  ),
+                                ],
                               ),
-                              Expanded(
-                                child: Column(
-                                  crossAxisAlignment: CrossAxisAlignment.start,
-                                  children: [
-                                    Text(
-                                      tuple.item2,
-                                      style: STextStyles.largeMedium14(context),
-                                    ),
-                                    const SizedBox(
-                                      height: 2,
-                                    ),
-                                    Text(
-                                      ticker.toUpperCase(),
-                                      style: STextStyles.smallMed12(context)
-                                          .copyWith(
-                                        color: Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .textSubtitle1,
-                                      ),
-                                    ),
-                                  ],
-                                ),
-                              ),
-                            ],
-                          ),
+                            ),
+                          ],
                         ),
                       ),
-                    );
-                  },
-                ),
+                    ),
+                  );
+                },
               ),
             ),
-          ],
-        ),
+          ),
+        ],
       ),
     );
   }
diff --git a/lib/pages/exchange_view/exchange_coin_selection/floating_rate_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/floating_rate_currency_selection_view.dart
index e1c1addd2..eb7a99299 100644
--- a/lib/pages/exchange_view/exchange_coin_selection/floating_rate_currency_selection_view.dart
+++ b/lib/pages/exchange_view/exchange_coin_selection/floating_rate_currency_selection_view.dart
@@ -6,6 +6,8 @@ import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
 import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
 import 'package:stackwallet/widgets/loading_indicator.dart';
@@ -13,8 +15,6 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 import 'package:stackwallet/widgets/textfield_icon_button.dart';
 
-import 'package:stackwallet/utilities/util.dart';
-
 class FloatingRateCurrencySelectionView extends StatefulWidget {
   const FloatingRateCurrencySelectionView({
     Key? key,
@@ -76,96 +76,109 @@ class _FloatingRateCurrencySelectionViewState
 
   @override
   Widget build(BuildContext context) {
-    return Scaffold(
-      backgroundColor: Theme.of(context).extension<StackColors>()!.background,
-      appBar: AppBar(
-        leading: AppBarBackButton(
-          onPressed: () async {
-            if (FocusScope.of(context).hasFocus) {
-              FocusScope.of(context).unfocus();
-              await Future<void>.delayed(const Duration(milliseconds: 50));
-            }
-            if (mounted) {
-              Navigator.of(context).pop();
-            }
-          },
-        ),
-        title: Text(
-          "Choose a coin to exchange",
-          style: STextStyles.pageTitleH2(context),
-        ),
-      ),
-      body: Padding(
-        padding: const EdgeInsets.symmetric(
-          horizontal: 16,
-        ),
-        child: Column(
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
+    final isDesktop = Util.isDesktop;
+    return ConditionalParent(
+      condition: !isDesktop,
+      builder: (child) {
+        return Scaffold(
+          backgroundColor:
+              Theme.of(context).extension<StackColors>()!.background,
+          appBar: AppBar(
+            leading: AppBarBackButton(
+              onPressed: () async {
+                if (FocusScope.of(context).hasFocus) {
+                  FocusScope.of(context).unfocus();
+                  await Future<void>.delayed(const Duration(milliseconds: 50));
+                }
+                if (mounted) {
+                  Navigator.of(context).pop();
+                }
+              },
+            ),
+            title: Text(
+              "Choose a coin to exchange",
+              style: STextStyles.pageTitleH2(context),
+            ),
+          ),
+          body: Padding(
+            padding: const EdgeInsets.symmetric(
+              horizontal: 16,
+            ),
+            child: child,
+          ),
+        );
+      },
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max,
+        children: [
+          if (!isDesktop)
             const SizedBox(
               height: 16,
             ),
-            ClipRRect(
-              borderRadius: BorderRadius.circular(
-                Constants.size.circularBorderRadius,
-              ),
-              child: TextField(
-                autocorrect: Util.isDesktop ? false : true,
-                enableSuggestions: Util.isDesktop ? false : true,
-                controller: _searchController,
-                focusNode: _searchFocusNode,
-                onChanged: filter,
-                style: STextStyles.field(context),
-                decoration: standardInputDecoration(
-                  "Search",
-                  _searchFocusNode,
-                  context,
-                ).copyWith(
-                  prefixIcon: Padding(
-                    padding: const EdgeInsets.symmetric(
-                      horizontal: 10,
-                      vertical: 16,
-                    ),
-                    child: SvgPicture.asset(
-                      Assets.svg.search,
-                      width: 16,
-                      height: 16,
-                    ),
+          ClipRRect(
+            borderRadius: BorderRadius.circular(
+              Constants.size.circularBorderRadius,
+            ),
+            child: TextField(
+              autocorrect: !isDesktop,
+              enableSuggestions: !isDesktop,
+              controller: _searchController,
+              focusNode: _searchFocusNode,
+              onChanged: filter,
+              style: STextStyles.field(context),
+              decoration: standardInputDecoration(
+                "Search",
+                _searchFocusNode,
+                context,
+                desktopMed: isDesktop,
+              ).copyWith(
+                prefixIcon: Padding(
+                  padding: const EdgeInsets.symmetric(
+                    horizontal: 10,
+                    vertical: 16,
+                  ),
+                  child: SvgPicture.asset(
+                    Assets.svg.search,
+                    width: 16,
+                    height: 16,
                   ),
-                  suffixIcon: _searchController.text.isNotEmpty
-                      ? Padding(
-                          padding: const EdgeInsets.only(right: 0),
-                          child: UnconstrainedBox(
-                            child: Row(
-                              children: [
-                                TextFieldIconButton(
-                                  child: const XIcon(),
-                                  onTap: () async {
-                                    setState(() {
-                                      _searchController.text = "";
-                                    });
-                                    filter("");
-                                  },
-                                ),
-                              ],
-                            ),
-                          ),
-                        )
-                      : null,
                 ),
+                suffixIcon: _searchController.text.isNotEmpty
+                    ? Padding(
+                        padding: const EdgeInsets.only(right: 0),
+                        child: UnconstrainedBox(
+                          child: Row(
+                            children: [
+                              TextFieldIconButton(
+                                child: const XIcon(),
+                                onTap: () async {
+                                  setState(() {
+                                    _searchController.text = "";
+                                  });
+                                  filter("");
+                                },
+                              ),
+                            ],
+                          ),
+                        ),
+                      )
+                    : null,
               ),
             ),
-            const SizedBox(
-              height: 10,
-            ),
-            Text(
-              "Popular coins",
-              style: STextStyles.smallMed12(context),
-            ),
-            const SizedBox(
-              height: 12,
-            ),
-            Builder(builder: (context) {
+          ),
+          const SizedBox(
+            height: 10,
+          ),
+          Text(
+            "Popular coins",
+            style: STextStyles.smallMed12(context),
+          ),
+          const SizedBox(
+            height: 12,
+          ),
+          Flexible(
+            child: Builder(builder: (context) {
               final items = _currencies
                   .where((e) => Coin.values
                       .where((coin) =>
@@ -177,6 +190,7 @@ class _FloatingRateCurrencySelectionViewState
                 padding: const EdgeInsets.all(0),
                 child: ListView.builder(
                   shrinkWrap: true,
+                  primary: isDesktop ? false : null,
                   itemCount: items.length,
                   itemBuilder: (builderContext, index) {
                     return Padding(
@@ -234,80 +248,81 @@ class _FloatingRateCurrencySelectionViewState
                 ),
               );
             }),
-            const SizedBox(
-              height: 20,
-            ),
-            Text(
-              "All coins",
-              style: STextStyles.smallMed12(context),
-            ),
-            const SizedBox(
-              height: 12,
-            ),
-            Flexible(
-              child: RoundedWhiteContainer(
-                padding: const EdgeInsets.all(0),
-                child: ListView.builder(
-                  shrinkWrap: true,
-                  itemCount: _currencies.length,
-                  itemBuilder: (builderContext, index) {
-                    return Padding(
-                      padding: const EdgeInsets.symmetric(vertical: 4),
-                      child: GestureDetector(
-                        onTap: () {
-                          Navigator.of(context).pop(_currencies[index]);
-                        },
-                        child: RoundedWhiteContainer(
-                          child: Row(
-                            children: [
-                              SizedBox(
+          ),
+          const SizedBox(
+            height: 20,
+          ),
+          Text(
+            "All coins",
+            style: STextStyles.smallMed12(context),
+          ),
+          const SizedBox(
+            height: 12,
+          ),
+          Flexible(
+            child: RoundedWhiteContainer(
+              padding: const EdgeInsets.all(0),
+              child: ListView.builder(
+                shrinkWrap: true,
+                primary: isDesktop ? false : null,
+                itemCount: _currencies.length,
+                itemBuilder: (builderContext, index) {
+                  return Padding(
+                    padding: const EdgeInsets.symmetric(vertical: 4),
+                    child: GestureDetector(
+                      onTap: () {
+                        Navigator.of(context).pop(_currencies[index]);
+                      },
+                      child: RoundedWhiteContainer(
+                        child: Row(
+                          children: [
+                            SizedBox(
+                              width: 24,
+                              height: 24,
+                              child: SvgPicture.network(
+                                _currencies[index].image,
                                 width: 24,
                                 height: 24,
-                                child: SvgPicture.network(
-                                  _currencies[index].image,
-                                  width: 24,
-                                  height: 24,
-                                  placeholderBuilder: (_) =>
-                                      const LoadingIndicator(),
-                                ),
+                                placeholderBuilder: (_) =>
+                                    const LoadingIndicator(),
                               ),
-                              const SizedBox(
-                                width: 10,
+                            ),
+                            const SizedBox(
+                              width: 10,
+                            ),
+                            Expanded(
+                              child: Column(
+                                crossAxisAlignment: CrossAxisAlignment.start,
+                                children: [
+                                  Text(
+                                    _currencies[index].name,
+                                    style: STextStyles.largeMedium14(context),
+                                  ),
+                                  const SizedBox(
+                                    height: 2,
+                                  ),
+                                  Text(
+                                    _currencies[index].ticker.toUpperCase(),
+                                    style: STextStyles.smallMed12(context)
+                                        .copyWith(
+                                      color: Theme.of(context)
+                                          .extension<StackColors>()!
+                                          .textSubtitle1,
+                                    ),
+                                  ),
+                                ],
                               ),
-                              Expanded(
-                                child: Column(
-                                  crossAxisAlignment: CrossAxisAlignment.start,
-                                  children: [
-                                    Text(
-                                      _currencies[index].name,
-                                      style: STextStyles.largeMedium14(context),
-                                    ),
-                                    const SizedBox(
-                                      height: 2,
-                                    ),
-                                    Text(
-                                      _currencies[index].ticker.toUpperCase(),
-                                      style: STextStyles.smallMed12(context)
-                                          .copyWith(
-                                        color: Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .textSubtitle1,
-                                      ),
-                                    ),
-                                  ],
-                                ),
-                              ),
-                            ],
-                          ),
+                            ),
+                          ],
                         ),
                       ),
-                    );
-                  },
-                ),
+                    ),
+                  );
+                },
               ),
             ),
-          ],
-        ),
+          ),
+        ],
       ),
     );
   }
diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart
index 148c74920..cdc6f16b9 100644
--- a/lib/pages/exchange_view/exchange_form.dart
+++ b/lib/pages/exchange_view/exchange_form.dart
@@ -39,6 +39,7 @@ import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/desktop/simple_desktop_dialog.dart';
 import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/rounded_container.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_dialog.dart';
 import 'package:tuple/tuple.dart';
 
@@ -410,13 +411,65 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
       }
     }).toList(growable: false);
 
-    final result = await Navigator.of(context).push(
-      MaterialPageRoute<dynamic>(
-        builder: (_) => FloatingRateCurrencySelectionView(
-          currencies: tickers,
-        ),
-      ),
-    );
+    final result = isDesktop
+        ? await showDialog<Currency?>(
+            context: context,
+            builder: (context) {
+              return DesktopDialog(
+                maxHeight: 700,
+                maxWidth: 580,
+                child: Column(
+                  children: [
+                    Row(
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                      children: [
+                        Padding(
+                          padding: const EdgeInsets.only(
+                            left: 32,
+                          ),
+                          child: Text(
+                            "Choose a coin to exchange",
+                            style: STextStyles.desktopH3(context),
+                          ),
+                        ),
+                        const DesktopDialogCloseButton(),
+                      ],
+                    ),
+                    Expanded(
+                      child: Padding(
+                        padding: const EdgeInsets.only(
+                          left: 32,
+                          right: 32,
+                          bottom: 32,
+                        ),
+                        child: Row(
+                          children: [
+                            Expanded(
+                              child: RoundedWhiteContainer(
+                                padding: const EdgeInsets.all(16),
+                                borderColor: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .background,
+                                child: FloatingRateCurrencySelectionView(
+                                  currencies: tickers,
+                                ),
+                              ),
+                            ),
+                          ],
+                        ),
+                      ),
+                    ),
+                  ],
+                ),
+              );
+            })
+        : await Navigator.of(context).push(
+            MaterialPageRoute<dynamic>(
+              builder: (_) => FloatingRateCurrencySelectionView(
+                currencies: tickers,
+              ),
+            ),
+          );
 
     if (mounted && result is Currency) {
       onSelected(result);
@@ -490,15 +543,73 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
           .toList(growable: false);
     }
 
-    final result = await Navigator.of(context).push(
-      MaterialPageRoute<dynamic>(
-        builder: (_) => FixedRateMarketPairCoinSelectionView(
-          markets: marketsThatPairWithExcludedTicker,
-          currencies: ref.read(availableChangeNowCurrenciesProvider).currencies,
-          isFrom: excludedTicker != fromTicker,
-        ),
-      ),
-    );
+    final result = isDesktop
+        ? await showDialog<String?>(
+            context: context,
+            builder: (context) {
+              return DesktopDialog(
+                maxHeight: 700,
+                maxWidth: 580,
+                child: Column(
+                  children: [
+                    Row(
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                      children: [
+                        Padding(
+                          padding: const EdgeInsets.only(
+                            left: 32,
+                          ),
+                          child: Text(
+                            "Choose a coin to exchange",
+                            style: STextStyles.desktopH3(context),
+                          ),
+                        ),
+                        const DesktopDialogCloseButton(),
+                      ],
+                    ),
+                    Expanded(
+                      child: Padding(
+                        padding: const EdgeInsets.only(
+                          left: 32,
+                          right: 32,
+                          bottom: 32,
+                        ),
+                        child: Row(
+                          children: [
+                            Expanded(
+                              child: RoundedWhiteContainer(
+                                padding: const EdgeInsets.all(16),
+                                borderColor: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .background,
+                                child: FixedRateMarketPairCoinSelectionView(
+                                  markets: marketsThatPairWithExcludedTicker,
+                                  currencies: ref
+                                      .read(
+                                          availableChangeNowCurrenciesProvider)
+                                      .currencies,
+                                  isFrom: excludedTicker != fromTicker,
+                                ),
+                              ),
+                            ),
+                          ],
+                        ),
+                      ),
+                    ),
+                  ],
+                ),
+              );
+            })
+        : await Navigator.of(context).push(
+            MaterialPageRoute<dynamic>(
+              builder: (_) => FixedRateMarketPairCoinSelectionView(
+                markets: marketsThatPairWithExcludedTicker,
+                currencies:
+                    ref.read(availableChangeNowCurrenciesProvider).currencies,
+                isFrom: excludedTicker != fromTicker,
+              ),
+            ),
+          );
 
     if (mounted && result is String) {
       onSelected(result);

From 3e9039ac90b724cb8886e17e6907c677fcdc36d2 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 11:26:34 -0600
Subject: [PATCH 071/100] show to and from tickers in exchange steps flow

---
 lib/pages/exchange_view/exchange_form.dart                 | 2 ++
 .../desktop_exchange/exchange_steps/step_scaffold.dart     | 7 ++++++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart
index cdc6f16b9..7faa83a35 100644
--- a/lib/pages/exchange_view/exchange_form.dart
+++ b/lib/pages/exchange_view/exchange_form.dart
@@ -1030,6 +1030,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
                 maxHeight: double.infinity,
                 child: StepScaffold(
                   step: 2,
+                  model: model,
                   body: DesktopStep2(
                     model: model,
                   ),
@@ -1057,6 +1058,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
                 maxHeight: double.infinity,
                 child: StepScaffold(
                   step: 1,
+                  model: model,
                   body: DesktopStep1(
                     model: model,
                   ),
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart
index 62a293c27..8dbaf9580 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart
@@ -1,4 +1,5 @@
 import 'package:flutter/material.dart';
+import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_exchange_steps_indicator.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@@ -8,10 +9,12 @@ class StepScaffold extends StatefulWidget {
     Key? key,
     required this.body,
     required this.step,
+    required this.model,
   }) : super(key: key);
 
   final Widget body;
   final int step;
+  final IncompleteExchangeModel model;
 
   @override
   State<StepScaffold> createState() => _StepScaffoldState();
@@ -19,10 +22,12 @@ class StepScaffold extends StatefulWidget {
 
 class _StepScaffoldState extends State<StepScaffold> {
   int currentStep = 0;
+  late final IncompleteExchangeModel model;
 
   @override
   void initState() {
     currentStep = widget.step;
+    model = widget.model;
     super.initState();
   }
 
@@ -38,7 +43,7 @@ class _StepScaffoldState extends State<StepScaffold> {
               iconSize: 23,
             ),
             Text(
-              "Exchange XXX to XXX",
+              "Exchange ${model.sendTicker.toUpperCase()} to ${model.receiveTicker.toUpperCase()}",
               style: STextStyles.desktopH3(context),
             ),
           ],

From 3fca3d8b1e9d7ce15a5610c60342f94363e93cf5 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 12:03:15 -0600
Subject: [PATCH 072/100] desktop exchange flow styling and choose addresses
 from addressbook functionality

---
 .../subwidgets/desktop_step_1.dart            |  23 ++-
 .../subwidgets/desktop_step_2.dart            | 139 +++++++++++++-----
 2 files changed, 121 insertions(+), 41 deletions(-)

diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
index 942747ea2..a97b722ef 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
@@ -2,10 +2,13 @@ import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
 import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
 import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
@@ -97,8 +100,24 @@ class DesktopStep1 extends ConsumerWidget {
                 child: PrimaryButton(
                   label: "Next",
                   buttonHeight: ButtonHeight.l,
-                  onPressed: () {
-                    // todo
+                  onPressed: () async {
+                    await showDialog<void>(
+                      context: context,
+                      barrierColor: Colors.transparent,
+                      builder: (context) {
+                        return DesktopDialog(
+                          maxWidth: 720,
+                          maxHeight: double.infinity,
+                          child: StepScaffold(
+                            step: 2,
+                            model: model,
+                            body: DesktopStep2(
+                              model: model,
+                            ),
+                          ),
+                        );
+                      },
+                    );
                   },
                 ),
               ),
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
index e1c5a5620..38c01822e 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
@@ -2,10 +2,8 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
-import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
-import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart';
 import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
-import 'package:stackwallet/providers/exchange/exchange_flow_is_active_state_provider.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart';
 import 'package:stackwallet/providers/exchange/exchange_send_from_wallet_id_provider.dart';
 import 'package:stackwallet/providers/global/wallets_provider.dart';
 import 'package:stackwallet/utilities/clipboard_interface.dart';
@@ -24,6 +22,10 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 import 'package:stackwallet/widgets/textfield_icon_button.dart';
 
+import '../../../../models/contact_address_entry.dart';
+import '../../../../widgets/desktop/desktop_dialog.dart';
+import '../../../../widgets/desktop/desktop_dialog_close_button.dart';
+
 class DesktopStep2 extends ConsumerStatefulWidget {
   const DesktopStep2({
     Key? key,
@@ -105,42 +107,96 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
     }
   }
 
-  void selectRecipientFromAddressBook() {
-    ref.read(exchangeFlowIsActiveStateProvider.state).state = true;
-    Navigator.of(context)
-        .pushNamed(
-      AddressBookView.routeName,
-    )
-        .then((_) {
-      ref.read(exchangeFlowIsActiveStateProvider.state).state = false;
+  void selectRecipientFromAddressBook() async {
+    final coin = coinFromTickerCaseInsensitive(
+      model.receiveTicker,
+    );
 
-      final address =
-          ref.read(exchangeFromAddressBookAddressStateProvider.state).state;
-      if (address.isNotEmpty) {
-        _toController.text = address;
-        model.recipientAddress = _toController.text;
-        ref.read(exchangeFromAddressBookAddressStateProvider.state).state = "";
-      }
-    });
+    final entry = await showDialog<ContactAddressEntry?>(
+      context: context,
+      barrierColor: Colors.transparent,
+      builder: (context) => DesktopDialog(
+        maxWidth: 720,
+        maxHeight: 670,
+        child: Column(
+          mainAxisSize: MainAxisSize.min,
+          children: [
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Padding(
+                  padding: const EdgeInsets.only(
+                    left: 32,
+                  ),
+                  child: Text(
+                    "Address book",
+                    style: STextStyles.desktopH3(context),
+                  ),
+                ),
+                const DesktopDialogCloseButton(),
+              ],
+            ),
+            Expanded(
+              child: AddressBookAddressChooser(
+                coin: coin,
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+
+    if (entry != null) {
+      _toController.text = entry.address;
+      model.recipientAddress = entry.address;
+      setState(() {});
+    }
   }
 
-  void selectRefundFromAddressBook() {
-    ref.read(exchangeFlowIsActiveStateProvider.state).state = true;
-    Navigator.of(context)
-        .pushNamed(
-      AddressBookView.routeName,
-    )
-        .then(
-      (_) {
-        ref.read(exchangeFlowIsActiveStateProvider.state).state = false;
-        final address =
-            ref.read(exchangeFromAddressBookAddressStateProvider.state).state;
-        if (address.isNotEmpty) {
-          _refundController.text = address;
-          model.refundAddress = _refundController.text;
-        }
-      },
+  void selectRefundFromAddressBook() async {
+    final coin = coinFromTickerCaseInsensitive(
+      model.sendTicker,
     );
+
+    final entry = await showDialog<ContactAddressEntry?>(
+      context: context,
+      barrierColor: Colors.transparent,
+      builder: (context) => DesktopDialog(
+        maxWidth: 720,
+        maxHeight: 670,
+        child: Column(
+          mainAxisSize: MainAxisSize.min,
+          children: [
+            Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Padding(
+                  padding: const EdgeInsets.only(
+                    left: 32,
+                  ),
+                  child: Text(
+                    "Address book",
+                    style: STextStyles.desktopH3(context),
+                  ),
+                ),
+                const DesktopDialogCloseButton(),
+              ],
+            ),
+            Expanded(
+              child: AddressBookAddressChooser(
+                coin: coin,
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+
+    if (entry != null) {
+      _refundController.text = entry.address;
+      model.refundAddress = entry.address;
+      setState(() {});
+    }
   }
 
   @override
@@ -198,10 +254,12 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
   @override
   Widget build(BuildContext context) {
     return Column(
+      crossAxisAlignment: CrossAxisAlignment.stretch,
       children: [
         Text(
           "Enter exchange details",
           style: STextStyles.desktopTextMedium(context),
+          textAlign: TextAlign.center,
         ),
         const SizedBox(
           height: 8,
@@ -209,6 +267,7 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
         Text(
           "Enter your recipient and refund addresses",
           style: STextStyles.desktopTextExtraExtraSmall(context),
+          textAlign: TextAlign.center,
         ),
         const SizedBox(
           height: 20,
@@ -231,7 +290,7 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
           ],
         ),
         const SizedBox(
-          height: 4,
+          height: 10,
         ),
         ClipRRect(
           borderRadius: BorderRadius.circular(
@@ -321,9 +380,10 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
           ),
         ),
         const SizedBox(
-          height: 6,
+          height: 10,
         ),
         RoundedWhiteContainer(
+          borderColor: Theme.of(context).extension<StackColors>()!.background,
           child: Text(
             "This is the wallet where your ${model.receiveTicker.toUpperCase()} will be sent to.",
             style: STextStyles.desktopTextExtraExtraSmall(context),
@@ -350,7 +410,7 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
           ],
         ),
         const SizedBox(
-          height: 4,
+          height: 10,
         ),
         ClipRRect(
           borderRadius: BorderRadius.circular(
@@ -380,6 +440,7 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
               "Enter ${model.sendTicker.toUpperCase()} refund address",
               _refundFocusNode,
               context,
+              desktopMed: true,
             ).copyWith(
               contentPadding: const EdgeInsets.only(
                 left: 16,
@@ -441,7 +502,7 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
           ),
         ),
         const SizedBox(
-          height: 6,
+          height: 10,
         ),
         RoundedWhiteContainer(
           borderColor: Theme.of(context).extension<StackColors>()!.background,

From 7e8f0db96726f509bfb9f20ef18de7b1a5021ed8 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 12:07:15 -0600
Subject: [PATCH 073/100] long address layout fix

---
 .../sub_widgets/contact_list_item.dart        | 68 +++++++++++--------
 1 file changed, 40 insertions(+), 28 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart
index 7acfaae9e..d7bfefb1f 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart
@@ -87,35 +87,47 @@ class _ContactListItemState extends ConsumerState<ContactListItem> {
                         child: Row(
                           mainAxisAlignment: MainAxisAlignment.spaceBetween,
                           children: [
-                            Row(
-                              children: [
-                                WalletInfoCoinIcon(coin: e.coin),
-                                const SizedBox(
-                                  width: 12,
-                                ),
-                                Column(
-                                  mainAxisSize: MainAxisSize.min,
-                                  crossAxisAlignment: CrossAxisAlignment.start,
-                                  children: [
-                                    Text(
-                                      "${contactId == "default" ? e.other! : e.label} (${e.coin.ticker})",
-                                      style: STextStyles
-                                              .desktopTextExtraExtraSmall(
-                                                  context)
-                                          .copyWith(
-                                        color: Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .textDark,
-                                      ),
+                            Flexible(
+                              child: Row(
+                                children: [
+                                  WalletInfoCoinIcon(coin: e.coin),
+                                  const SizedBox(
+                                    width: 12,
+                                  ),
+                                  Flexible(
+                                    child: Column(
+                                      mainAxisSize: MainAxisSize.min,
+                                      crossAxisAlignment:
+                                          CrossAxisAlignment.start,
+                                      children: [
+                                        Text(
+                                          "${contactId == "default" ? e.other! : e.label} (${e.coin.ticker})",
+                                          style: STextStyles
+                                                  .desktopTextExtraExtraSmall(
+                                                      context)
+                                              .copyWith(
+                                            color: Theme.of(context)
+                                                .extension<StackColors>()!
+                                                .textDark,
+                                          ),
+                                        ),
+                                        Row(
+                                          children: [
+                                            Flexible(
+                                              child: Text(
+                                                e.address,
+                                                style: STextStyles
+                                                    .desktopTextExtraExtraSmall(
+                                                        context),
+                                              ),
+                                            ),
+                                          ],
+                                        ),
+                                      ],
                                     ),
-                                    Text(
-                                      e.address,
-                                      style: STextStyles
-                                          .desktopTextExtraExtraSmall(context),
-                                    ),
-                                  ],
-                                ),
-                              ],
+                                  ),
+                                ],
+                              ),
                             ),
                             BlueTextButton(
                               text: "Select wallet",

From 04b982fb250156d3d96e3b44e955a2bd890dfd02 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 13:21:52 -0600
Subject: [PATCH 074/100] desktop exchange choose from stack address ui

---
 .../subwidgets/desktop_step_2.dart            |  50 ++-
 .../subwidgets/desktop_choose_from_stack.dart | 329 ++++++++++++++++++
 2 files changed, 364 insertions(+), 15 deletions(-)
 create mode 100644 lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_choose_from_stack.dart

diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
index 38c01822e..270b98fc7 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
-import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_choose_from_stack.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart';
 import 'package:stackwallet/providers/exchange/exchange_send_from_wallet_id_provider.dart';
 import 'package:stackwallet/providers/global/wallets_provider.dart';
@@ -64,12 +64,21 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
       final coin = coinFromTickerCaseInsensitive(
         model.receiveTicker,
       );
-      Navigator.of(context)
-          .pushNamed(
-        ChooseFromStackView.routeName,
-        arguments: coin,
-      )
-          .then((value) async {
+
+      showDialog<String?>(
+        context: context,
+        barrierColor: Colors.transparent,
+        builder: (context) => DesktopDialog(
+          maxWidth: 720,
+          maxHeight: 670,
+          child: Padding(
+            padding: const EdgeInsets.all(32),
+            child: DesktopChooseFromStack(
+              coin: coin,
+            ),
+          ),
+        ),
+      ).then((value) async {
         if (value is String) {
           final manager =
               ref.read(walletsChangeNotifierProvider).getManager(value);
@@ -88,12 +97,21 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
       final coin = coinFromTickerCaseInsensitive(
         model.sendTicker,
       );
-      Navigator.of(context)
-          .pushNamed(
-        ChooseFromStackView.routeName,
-        arguments: coin,
-      )
-          .then((value) async {
+
+      showDialog<String?>(
+        context: context,
+        barrierColor: Colors.transparent,
+        builder: (context) => DesktopDialog(
+          maxWidth: 720,
+          maxHeight: 670,
+          child: Padding(
+            padding: const EdgeInsets.all(32),
+            child: DesktopChooseFromStack(
+              coin: coin,
+            ),
+          ),
+        ),
+      ).then((value) async {
         if (value is String) {
           final manager =
               ref.read(walletsChangeNotifierProvider).getManager(value);
@@ -366,7 +384,8 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
                                   ? const ClipboardIcon()
                                   : const XIcon(),
                             ),
-                      if (_toController.text.isEmpty)
+                      if (_toController.text.isEmpty &&
+                          isStackCoin(model.receiveTicker))
                         TextFieldIconButton(
                           key: const Key("sendViewAddressBookButtonKey"),
                           onTap: selectRecipientFromAddressBook,
@@ -488,7 +507,8 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
                                   ? const ClipboardIcon()
                                   : const XIcon(),
                             ),
-                      if (_refundController.text.isEmpty)
+                      if (_refundController.text.isEmpty &&
+                          isStackCoin(model.sendTicker))
                         TextFieldIconButton(
                           key: const Key("sendViewAddressBookButtonKey"),
                           onTap: selectRefundFromAddressBook,
diff --git a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_choose_from_stack.dart b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_choose_from_stack.dart
new file mode 100644
index 000000000..a3fb91f61
--- /dev/null
+++ b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_choose_from_stack.dart
@@ -0,0 +1,329 @@
+import 'package:decimal/decimal.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:stackwallet/providers/providers.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/constants.dart';
+import 'package:stackwallet/utilities/enums/coin_enum.dart';
+import 'package:stackwallet/utilities/format.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/animated_text.dart';
+import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+import 'package:stackwallet/widgets/stack_text_field.dart';
+import 'package:stackwallet/widgets/textfield_icon_button.dart';
+import 'package:stackwallet/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart';
+
+class DesktopChooseFromStack extends ConsumerStatefulWidget {
+  const DesktopChooseFromStack({
+    Key? key,
+    required this.coin,
+  }) : super(key: key);
+
+  final Coin coin;
+
+  @override
+  ConsumerState<DesktopChooseFromStack> createState() =>
+      _DesktopChooseFromStackState();
+}
+
+class _DesktopChooseFromStackState
+    extends ConsumerState<DesktopChooseFromStack> {
+  late final TextEditingController _searchController;
+  late final FocusNode searchFieldFocusNode;
+
+  String _searchTerm = "";
+
+  List<String> filter(List<String> walletIds, String searchTerm) {
+    if (searchTerm.isEmpty) {
+      return walletIds;
+    }
+
+    final List<String> result = [];
+    for (final walletId in walletIds) {
+      final manager =
+          ref.read(walletsChangeNotifierProvider).getManager(walletId);
+
+      if (manager.walletName.toLowerCase().contains(searchTerm.toLowerCase())) {
+        result.add(walletId);
+      }
+    }
+
+    return result;
+  }
+
+  @override
+  void initState() {
+    searchFieldFocusNode = FocusNode();
+    _searchController = TextEditingController();
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    _searchController.dispose();
+    searchFieldFocusNode.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        Text(
+          "Choose from Stack",
+          style: STextStyles.desktopH3(context),
+        ),
+        const SizedBox(
+          height: 28,
+        ),
+        ClipRRect(
+          borderRadius: BorderRadius.circular(
+            Constants.size.circularBorderRadius,
+          ),
+          child: TextField(
+            autocorrect: false,
+            enableSuggestions: false,
+            controller: _searchController,
+            focusNode: searchFieldFocusNode,
+            onChanged: (value) {
+              setState(() {
+                _searchTerm = value;
+              });
+            },
+            style: STextStyles.desktopTextExtraSmall(context).copyWith(
+              color: Theme.of(context)
+                  .extension<StackColors>()!
+                  .textFieldActiveText,
+              height: 1.8,
+            ),
+            decoration: standardInputDecoration(
+              "Search",
+              searchFieldFocusNode,
+              context,
+              desktopMed: true,
+            ).copyWith(
+              prefixIcon: Padding(
+                padding: const EdgeInsets.symmetric(
+                  horizontal: 12,
+                  vertical: 18,
+                ),
+                child: SvgPicture.asset(
+                  Assets.svg.search,
+                  width: 20,
+                  height: 20,
+                ),
+              ),
+              suffixIcon: _searchController.text.isNotEmpty
+                  ? Padding(
+                      padding: const EdgeInsets.only(right: 0),
+                      child: UnconstrainedBox(
+                        child: Row(
+                          children: [
+                            TextFieldIconButton(
+                              child: const XIcon(),
+                              onTap: () async {
+                                setState(() {
+                                  _searchController.text = "";
+                                  _searchTerm = "";
+                                });
+                              },
+                            ),
+                          ],
+                        ),
+                      ),
+                    )
+                  : null,
+            ),
+          ),
+        ),
+        const SizedBox(
+          height: 16,
+        ),
+        Flexible(
+          child: Builder(
+            builder: (context) {
+              List<String> walletIds = ref.watch(
+                walletsChangeNotifierProvider.select(
+                  (value) => value.getWalletIdsFor(coin: widget.coin),
+                ),
+              );
+
+              if (walletIds.isEmpty) {
+                return Column(
+                  children: [
+                    RoundedWhiteContainer(
+                      borderColor: Theme.of(context)
+                          .extension<StackColors>()!
+                          .background,
+                      child: Center(
+                        child: Text(
+                          "No ${widget.coin.ticker.toUpperCase()} wallets",
+                          style:
+                              STextStyles.desktopTextExtraExtraSmall(context),
+                        ),
+                      ),
+                    ),
+                  ],
+                );
+              }
+
+              walletIds = filter(walletIds, _searchTerm);
+
+              return ListView.separated(
+                primary: false,
+                itemCount: walletIds.length,
+                separatorBuilder: (_, __) => const SizedBox(
+                  height: 5,
+                ),
+                itemBuilder: (context, index) {
+                  final manager = ref.watch(walletsChangeNotifierProvider
+                      .select((value) => value.getManager(walletIds[index])));
+
+                  return RoundedWhiteContainer(
+                    borderColor:
+                        Theme.of(context).extension<StackColors>()!.background,
+                    padding: const EdgeInsets.symmetric(
+                      horizontal: 20,
+                      vertical: 14,
+                    ),
+                    child: Row(
+                      mainAxisAlignment: MainAxisAlignment.end,
+                      children: [
+                        Row(
+                          children: [
+                            WalletInfoCoinIcon(coin: widget.coin),
+                            const SizedBox(
+                              width: 12,
+                            ),
+                            Text(
+                              manager.walletName,
+                              style: STextStyles.desktopTextExtraExtraSmall(
+                                      context)
+                                  .copyWith(
+                                color: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .textDark,
+                              ),
+                            ),
+                          ],
+                        ),
+                        const Spacer(),
+                        BalanceDisplay(
+                          walletId: walletIds[index],
+                        ),
+                        const SizedBox(
+                          width: 80,
+                        ),
+                        BlueTextButton(
+                          text: "Select wallet",
+                          onTap: () {
+                            Navigator.of(context).pop(manager.walletId);
+                          },
+                        ),
+                      ],
+                    ),
+                  );
+                },
+              );
+            },
+          ),
+        ),
+        const SizedBox(
+          height: 20,
+        ),
+        Row(
+          children: [
+            const Spacer(),
+            const SizedBox(
+              width: 16,
+            ),
+            Expanded(
+              child: SecondaryButton(
+                label: "Cancel",
+                buttonHeight: ButtonHeight.l,
+                onPressed: Navigator.of(context).pop,
+              ),
+            ),
+          ],
+        )
+      ],
+    );
+  }
+}
+
+class BalanceDisplay extends ConsumerStatefulWidget {
+  const BalanceDisplay({
+    Key? key,
+    required this.walletId,
+  }) : super(key: key);
+
+  final String walletId;
+
+  @override
+  ConsumerState<BalanceDisplay> createState() => _BalanceDisplayState();
+}
+
+class _BalanceDisplayState extends ConsumerState<BalanceDisplay> {
+  late final String walletId;
+
+  Decimal? _cachedBalance;
+
+  static const loopedText = [
+    "Loading balance   ",
+    "Loading balance.  ",
+    "Loading balance.. ",
+    "Loading balance..."
+  ];
+
+  @override
+  void initState() {
+    walletId = widget.walletId;
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final manager = ref.watch(walletsChangeNotifierProvider
+        .select((value) => value.getManager(walletId)));
+    final locale = ref.watch(
+        localeServiceChangeNotifierProvider.select((value) => value.locale));
+
+    return FutureBuilder(
+      future: manager.availableBalance,
+      builder: (context, AsyncSnapshot<Decimal> snapshot) {
+        if (snapshot.connectionState == ConnectionState.done &&
+            snapshot.hasData &&
+            snapshot.data != null) {
+          _cachedBalance = snapshot.data;
+        }
+
+        if (_cachedBalance == null) {
+          return AnimatedText(
+            stringsToLoopThrough: loopedText,
+            style: STextStyles.desktopTextExtraSmall(context).copyWith(
+              color: Theme.of(context).extension<StackColors>()!.textSubtitle1,
+            ),
+          );
+        } else {
+          return Text(
+            "${Format.localizedStringAsFixed(
+              value: _cachedBalance!,
+              locale: locale,
+              decimalPlaces: 8,
+            )} ${manager.coin.ticker}",
+            style: STextStyles.desktopTextExtraSmall(context).copyWith(
+              color: Theme.of(context).extension<StackColors>()!.textSubtitle1,
+            ),
+            textAlign: TextAlign.right,
+          );
+        }
+      },
+    );
+  }
+}

From f75e4ea2faf8e71c385aa05732ace062ee90a324 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 14:52:41 -0600
Subject: [PATCH 075/100] desktop delete routing fixes

---
 .../sub_widgets/delete_wallet_button.dart     | 113 ++++++++--
 .../sub_widgets/delete_wallet_keys_popup.dart | 204 +++++++++---------
 .../desktop_attention_delete_wallet.dart      |  27 ++-
 3 files changed, 207 insertions(+), 137 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
index 54f991c37..fd401d613 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
@@ -1,13 +1,13 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/svg.dart';
-import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart';
 import 'package:stackwallet/route_generator.dart';
 import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/constants.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 
-import 'desktop_delete_wallet_dialog.dart';
-
 class DeleteWalletButton extends ConsumerStatefulWidget {
   const DeleteWalletButton({
     Key? key,
@@ -26,8 +26,6 @@ class _DeleteWalletButton extends ConsumerState<DeleteWalletButton> {
   @override
   void initState() {
     walletId = widget.walletId;
-    final managerProvider =
-        ref.read(walletsChangeNotifierProvider).getManagerProvider(walletId);
 
     super.initState();
   }
@@ -38,25 +36,45 @@ class _DeleteWalletButton extends ConsumerState<DeleteWalletButton> {
       shape: RoundedRectangleBorder(
         borderRadius: BorderRadius.circular(1000),
       ),
-      onPressed: () {
-        showDialog<void>(
+      onPressed: () async {
+        final shouldOpenDeleteDialog = await showDialog<bool?>(
           context: context,
-          barrierDismissible: false,
-          builder: (context) => Navigator(
-            initialRoute: DesktopDeleteWalletDialog.routeName,
-            onGenerateRoute: RouteGenerator.generateRoute,
-            onGenerateInitialRoutes: (_, __) {
-              return [
-                RouteGenerator.generateRoute(
-                  RouteSettings(
-                    name: DesktopDeleteWalletDialog.routeName,
-                    arguments: walletId,
-                  ),
-                )
-              ];
-            },
-          ),
+          barrierColor: Colors.transparent,
+          builder: (context) {
+            return DeletePopupButton(
+              onTap: () async {
+                Navigator.of(context).pop(true);
+              },
+            );
+          },
         );
+
+        if (shouldOpenDeleteDialog == true) {
+          final result = await showDialog<bool?>(
+            context: context,
+            barrierDismissible: false,
+            builder: (context) => Navigator(
+              initialRoute: DesktopDeleteWalletDialog.routeName,
+              onGenerateRoute: RouteGenerator.generateRoute,
+              onGenerateInitialRoutes: (_, __) {
+                return [
+                  RouteGenerator.generateRoute(
+                    RouteSettings(
+                      name: DesktopDeleteWalletDialog.routeName,
+                      arguments: walletId,
+                    ),
+                  ),
+                ];
+              },
+            ),
+          );
+
+          if (result == true) {
+            if (mounted) {
+              Navigator.of(context).pop();
+            }
+          }
+        }
       },
       child: Padding(
         padding: const EdgeInsets.symmetric(
@@ -79,3 +97,54 @@ class _DeleteWalletButton extends ConsumerState<DeleteWalletButton> {
     );
   }
 }
+
+class DeletePopupButton extends StatefulWidget {
+  const DeletePopupButton({
+    Key? key,
+    this.onTap,
+  }) : super(key: key);
+
+  final VoidCallback? onTap;
+
+  @override
+  State<DeletePopupButton> createState() => _DeletePopupButtonState();
+}
+
+class _DeletePopupButtonState extends State<DeletePopupButton> {
+  @override
+  Widget build(BuildContext context) {
+    return Stack(
+      children: [
+        Positioned(
+          top: 24,
+          left: MediaQuery.of(context).size.width - 234,
+          child: MouseRegion(
+            cursor: SystemMouseCursors.click,
+            child: GestureDetector(
+              onTap: widget.onTap,
+              child: Container(
+                width: 210,
+                height: 70,
+                decoration: BoxDecoration(
+                  borderRadius: BorderRadius.circular(
+                    Constants.size.circularBorderRadius,
+                  ),
+                  color: Colors.red,
+                  boxShadow: [
+                    Theme.of(context)
+                        .extension<StackColors>()!
+                        .standardBoxShadow,
+                  ],
+                ),
+                child: Text(
+                  "Delete",
+                  style: STextStyles.desktopButtonSecondaryEnabled(context),
+                ),
+              ),
+            ),
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
index f70c2eadf..6b638bb75 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
@@ -1,11 +1,9 @@
-import 'dart:async';
-
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart';
-import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_stack_view.dart';
 import 'package:stackwallet/providers/global/wallets_provider.dart';
 import 'package:stackwallet/providers/global/wallets_service_provider.dart';
+import 'package:stackwallet/route_generator.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
@@ -61,8 +59,10 @@ class _DeleteWalletKeysPopup extends ConsumerState<DeleteWalletKeysPopup> {
               ),
               DesktopDialogCloseButton(
                 onPressedOverride: () {
-                  int count = 0;
-                  Navigator.of(context).popUntil((_) => count++ >= 2);
+                  Navigator.of(
+                    context,
+                    rootNavigator: true,
+                  ).pop();
                 },
               ),
             ],
@@ -117,106 +117,17 @@ class _DeleteWalletKeysPopup extends ConsumerState<DeleteWalletKeysPopup> {
                   child: PrimaryButton(
                     label: "Continue",
                     onPressed: () async {
-                      int count = 0;
-                      Navigator.of(context).popUntil((_) => count++ >= 2);
-
-                      unawaited(
-                        showDialog(
-                            context: context,
-                            builder: (context) {
-                              return DesktopDialog(
-                                maxHeight: 350,
-                                child: Column(
-                                  children: [
-                                    Row(
-                                      mainAxisAlignment: MainAxisAlignment.end,
-                                      children: [
-                                        DesktopDialogCloseButton(
-                                          onPressedOverride: () {
-                                            int count = 0;
-                                            Navigator.of(context)
-                                                .popUntil((_) => count++ >= 2);
-                                          },
-                                        ),
-                                      ],
-                                    ),
-                                    Column(
-                                      crossAxisAlignment:
-                                          CrossAxisAlignment.center,
-                                      children: [
-                                        Text(
-                                          "Thanks! "
-                                          "\n\nYour wallet will be deleted.",
-                                          style: STextStyles.desktopH2(context),
-                                          textAlign: TextAlign.center,
-                                        ),
-                                        const SizedBox(height: 50),
-                                        Row(
-                                          mainAxisAlignment:
-                                              MainAxisAlignment.center,
-                                          children: [
-                                            SecondaryButton(
-                                                width: 250,
-                                                buttonHeight: ButtonHeight.xl,
-                                                label: "Cancel",
-                                                onPressed: () {
-                                                  int count = 0;
-                                                  Navigator.of(context)
-                                                      .popUntil(
-                                                          (_) => count++ >= 2);
-                                                }),
-                                            const SizedBox(width: 16),
-                                            PrimaryButton(
-                                                width: 250,
-                                                buttonHeight: ButtonHeight.xl,
-                                                label: "Continue",
-                                                onPressed: () async {
-                                                  // int count = 0;
-                                                  // Navigator.of(context)
-                                                  //     .popUntil(
-                                                  //         (_) => count++ >= 2);
-
-                                                  final walletsInstance = ref.read(
-                                                      walletsChangeNotifierProvider);
-                                                  final manager = ref
-                                                      .read(
-                                                          walletsChangeNotifierProvider)
-                                                      .getManager(_walletId);
-
-                                                  final _managerWalletId =
-                                                      manager.walletId;
-
-                                                  await ref
-                                                      .read(
-                                                          walletsServiceChangeNotifierProvider)
-                                                      .deleteWallet(
-                                                          manager.walletName,
-                                                          true);
-
-                                                  if (mounted) {
-                                                    Navigator.of(context)
-                                                        .popUntil(
-                                                            ModalRoute.withName(
-                                                                MyStackView
-                                                                    .routeName));
-                                                  }
-
-                                                  // wait for widget tree to dispose of any widgets watching the manager
-                                                  await Future<void>.delayed(
-                                                      const Duration(
-                                                          seconds: 1));
-                                                  walletsInstance.removeWallet(
-                                                      walletId:
-                                                          _managerWalletId);
-                                                }),
-                                          ],
-                                        )
-                                      ],
-                                    ),
-                                  ],
-                                ),
-                              );
-                            }),
+                      await Navigator.of(context).push(
+                        RouteGenerator.getRoute(
+                          builder: (context) {
+                            return ConfirmDelete(
+                              walletId: _walletId,
+                            );
+                          },
+                          settings: const RouteSettings(
+                            name: "/desktopConfirmDelete",
+                          ),
+                        ),
                       );
                     },
                   ),
@@ -232,3 +143,86 @@ class _DeleteWalletKeysPopup extends ConsumerState<DeleteWalletKeysPopup> {
     );
   }
 }
+
+class ConfirmDelete extends ConsumerStatefulWidget {
+  const ConfirmDelete({
+    Key? key,
+    required this.walletId,
+  }) : super(key: key);
+
+  final String walletId;
+
+  @override
+  ConsumerState<ConfirmDelete> createState() => _ConfirmDeleteState();
+}
+
+class _ConfirmDeleteState extends ConsumerState<ConfirmDelete> {
+  @override
+  Widget build(BuildContext context) {
+    return DesktopDialog(
+      maxHeight: 350,
+      child: Column(
+        children: [
+          Row(
+            mainAxisAlignment: MainAxisAlignment.end,
+            children: const [
+              DesktopDialogCloseButton(),
+            ],
+          ),
+          Column(
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              Text(
+                "Thanks! "
+                "\n\nYour wallet will be deleted.",
+                style: STextStyles.desktopH2(context),
+                textAlign: TextAlign.center,
+              ),
+              const SizedBox(height: 50),
+              Row(
+                mainAxisAlignment: MainAxisAlignment.center,
+                children: [
+                  SecondaryButton(
+                    width: 250,
+                    buttonHeight: ButtonHeight.xl,
+                    label: "Cancel",
+                    onPressed: () {
+                      Navigator.of(context, rootNavigator: true).pop();
+                    },
+                  ),
+                  const SizedBox(width: 16),
+                  PrimaryButton(
+                    width: 250,
+                    buttonHeight: ButtonHeight.xl,
+                    label: "Continue",
+                    onPressed: () async {
+                      final walletsInstance =
+                          ref.read(walletsChangeNotifierProvider);
+                      final manager = ref
+                          .read(walletsChangeNotifierProvider)
+                          .getManager(widget.walletId);
+
+                      final _managerWalletId = manager.walletId;
+                      //
+                      await ref
+                          .read(walletsServiceChangeNotifierProvider)
+                          .deleteWallet(manager.walletName, true);
+
+                      if (mounted) {
+                        Navigator.of(context, rootNavigator: true).pop(true);
+                      }
+
+                      // wait for widget tree to dispose of any widgets watching the manager
+                      await Future<void>.delayed(const Duration(seconds: 1));
+                      walletsInstance.removeWallet(walletId: _managerWalletId);
+                    },
+                  ),
+                ],
+              ),
+            ],
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart
index 30546f60b..6eb04502e 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart
@@ -41,8 +41,10 @@ class _DesktopAttentionDeleteWallet
             children: [
               DesktopDialogCloseButton(
                 onPressedOverride: () {
-                  int count = 0;
-                  Navigator.of(context).popUntil((_) => count++ >= 2);
+                  Navigator.of(
+                    context,
+                    rootNavigator: true,
+                  ).pop();
                 },
               ),
             ],
@@ -87,8 +89,10 @@ class _DesktopAttentionDeleteWallet
                       buttonHeight: ButtonHeight.xl,
                       label: "Cancel",
                       onPressed: () {
-                        int count = 0;
-                        Navigator.of(context).popUntil((_) => count++ >= 2);
+                        Navigator.of(
+                          context,
+                          rootNavigator: true,
+                        ).pop();
                       },
                     ),
                     const SizedBox(width: 16),
@@ -102,12 +106,15 @@ class _DesktopAttentionDeleteWallet
                             .getManager(widget.walletId)
                             .mnemonic;
 
-                        await Navigator.of(context)
-                            .pushNamed(DeleteWalletKeysPopup.routeName,
-                                arguments: Tuple2(
-                                  widget.walletId,
-                                  words,
-                                ));
+                        if (mounted) {
+                          await Navigator.of(context).pushNamed(
+                            DeleteWalletKeysPopup.routeName,
+                            arguments: Tuple2(
+                              widget.walletId,
+                              words,
+                            ),
+                          );
+                        }
                       },
                     ),
                   ],

From 8a6025db4b308756eaf5cf91d50cdbd1e545a801 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 15:29:09 -0600
Subject: [PATCH 076/100] place node url and port on their own line

---
 .../add_edit_node_view.dart                   | 195 +++++++++---------
 1 file changed, 93 insertions(+), 102 deletions(-)

diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
index 606c4481f..9062314f0 100644
--- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
+++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
@@ -494,6 +494,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
         condition: isDesktop,
         builder: (child) => DesktopDialog(
           maxWidth: 580,
+          maxHeight: 500,
           child: Column(
             mainAxisSize: MainAxisSize.min,
             children: [
@@ -830,110 +831,100 @@ class _NodeFormState extends ConsumerState<NodeForm> {
         const SizedBox(
           height: 8,
         ),
-        Row(
-          children: [
-            Expanded(
-              child: ClipRRect(
-                borderRadius: BorderRadius.circular(
-                  Constants.size.circularBorderRadius,
-                ),
-                child: TextField(
-                  autocorrect: Util.isDesktop ? false : true,
-                  enableSuggestions: Util.isDesktop ? false : true,
-                  key: const Key("addCustomNodeNodeAddressFieldKey"),
-                  readOnly: widget.readOnly,
-                  enabled: enableField(_hostController),
-                  controller: _hostController,
-                  focusNode: _hostFocusNode,
-                  style: STextStyles.field(context),
-                  decoration: standardInputDecoration(
-                    (widget.coin != Coin.monero &&
-                            widget.coin != Coin.wownero &&
-                            widget.coin != Coin.epicCash)
-                        ? "IP address"
-                        : "Url",
-                    _hostFocusNode,
-                    context,
-                  ).copyWith(
-                    suffixIcon:
-                        !widget.readOnly && _hostController.text.isNotEmpty
-                            ? Padding(
-                                padding: const EdgeInsets.only(right: 0),
-                                child: UnconstrainedBox(
-                                  child: Row(
-                                    children: [
-                                      TextFieldIconButton(
-                                        child: const XIcon(),
-                                        onTap: () async {
-                                          _hostController.text = "";
-                                          _updateState();
-                                        },
-                                      ),
-                                    ],
-                                  ),
-                                ),
-                              )
-                            : null,
-                  ),
-                  onChanged: (newValue) {
-                    _updateState();
-                    setState(() {});
-                  },
-                ),
-              ),
+        ClipRRect(
+          borderRadius: BorderRadius.circular(
+            Constants.size.circularBorderRadius,
+          ),
+          child: TextField(
+            autocorrect: Util.isDesktop ? false : true,
+            enableSuggestions: Util.isDesktop ? false : true,
+            key: const Key("addCustomNodeNodeAddressFieldKey"),
+            readOnly: widget.readOnly,
+            enabled: enableField(_hostController),
+            controller: _hostController,
+            focusNode: _hostFocusNode,
+            style: STextStyles.field(context),
+            decoration: standardInputDecoration(
+              (widget.coin != Coin.monero &&
+                      widget.coin != Coin.wownero &&
+                      widget.coin != Coin.epicCash)
+                  ? "IP address"
+                  : "Url",
+              _hostFocusNode,
+              context,
+            ).copyWith(
+              suffixIcon: !widget.readOnly && _hostController.text.isNotEmpty
+                  ? Padding(
+                      padding: const EdgeInsets.only(right: 0),
+                      child: UnconstrainedBox(
+                        child: Row(
+                          children: [
+                            TextFieldIconButton(
+                              child: const XIcon(),
+                              onTap: () async {
+                                _hostController.text = "";
+                                _updateState();
+                              },
+                            ),
+                          ],
+                        ),
+                      ),
+                    )
+                  : null,
             ),
-            const SizedBox(
-              width: 12,
+            onChanged: (newValue) {
+              _updateState();
+              setState(() {});
+            },
+          ),
+        ),
+        const SizedBox(
+          height: 8,
+        ),
+        ClipRRect(
+          borderRadius: BorderRadius.circular(
+            Constants.size.circularBorderRadius,
+          ),
+          child: TextField(
+            autocorrect: Util.isDesktop ? false : true,
+            enableSuggestions: Util.isDesktop ? false : true,
+            key: const Key("addCustomNodeNodePortFieldKey"),
+            readOnly: widget.readOnly,
+            enabled: enableField(_portController),
+            controller: _portController,
+            focusNode: _portFocusNode,
+            inputFormatters: [FilteringTextInputFormatter.digitsOnly],
+            keyboardType: TextInputType.number,
+            style: STextStyles.field(context),
+            decoration: standardInputDecoration(
+              "Port",
+              _portFocusNode,
+              context,
+            ).copyWith(
+              suffixIcon: !widget.readOnly && _portController.text.isNotEmpty
+                  ? Padding(
+                      padding: const EdgeInsets.only(right: 0),
+                      child: UnconstrainedBox(
+                        child: Row(
+                          children: [
+                            TextFieldIconButton(
+                              child: const XIcon(),
+                              onTap: () async {
+                                _portController.text = "";
+                                _updateState();
+                              },
+                            ),
+                          ],
+                        ),
+                      ),
+                    )
+                  : null,
             ),
-            Expanded(
-              child: ClipRRect(
-                borderRadius: BorderRadius.circular(
-                  Constants.size.circularBorderRadius,
-                ),
-                child: TextField(
-                  autocorrect: Util.isDesktop ? false : true,
-                  enableSuggestions: Util.isDesktop ? false : true,
-                  key: const Key("addCustomNodeNodePortFieldKey"),
-                  readOnly: widget.readOnly,
-                  enabled: enableField(_portController),
-                  controller: _portController,
-                  focusNode: _portFocusNode,
-                  inputFormatters: [FilteringTextInputFormatter.digitsOnly],
-                  keyboardType: TextInputType.number,
-                  style: STextStyles.field(context),
-                  decoration: standardInputDecoration(
-                    "Port",
-                    _portFocusNode,
-                    context,
-                  ).copyWith(
-                    suffixIcon:
-                        !widget.readOnly && _portController.text.isNotEmpty
-                            ? Padding(
-                                padding: const EdgeInsets.only(right: 0),
-                                child: UnconstrainedBox(
-                                  child: Row(
-                                    children: [
-                                      TextFieldIconButton(
-                                        child: const XIcon(),
-                                        onTap: () async {
-                                          _portController.text = "";
-                                          _updateState();
-                                        },
-                                      ),
-                                    ],
-                                  ),
-                                ),
-                              )
-                            : null,
-                  ),
-                  onChanged: (newValue) {
-                    _updateState();
-                    setState(() {});
-                  },
-                ),
-              ),
-            ),
-          ],
+            onChanged: (newValue) {
+              _updateState();
+              setState(() {});
+            },
+          ),
         ),
         const SizedBox(
           height: 8,

From 66950ccc5059bbf04187180fb7c60665cd892c41 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Mon, 21 Nov 2022 14:40:11 -0700
Subject: [PATCH 077/100] delete popup styled

---
 .../sub_widgets/delete_wallet_button.dart     | 22 +++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
index fd401d613..f2553c2da 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
@@ -129,16 +129,30 @@ class _DeletePopupButtonState extends State<DeletePopupButton> {
                   borderRadius: BorderRadius.circular(
                     Constants.size.circularBorderRadius,
                   ),
-                  color: Colors.red,
+                  color: Theme.of(context).extension<StackColors>()!.popupBG,
                   boxShadow: [
                     Theme.of(context)
                         .extension<StackColors>()!
                         .standardBoxShadow,
                   ],
                 ),
-                child: Text(
-                  "Delete",
-                  style: STextStyles.desktopButtonSecondaryEnabled(context),
+                child: Row(
+                  mainAxisAlignment: MainAxisAlignment.start,
+                  children: [
+                    const SizedBox(width: 24),
+                    SvgPicture.asset(
+                      Assets.svg.trash,
+                    ),
+                    const SizedBox(width: 14),
+                    Text(
+                      "Delete wallet",
+                      style: STextStyles.desktopTextExtraExtraSmall(context)
+                          .copyWith(
+                              color: Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textDark),
+                    ),
+                  ],
                 ),
               ),
             ),

From e099089d04a3154fbb1cd61fc331d0435e6aeba4 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Mon, 21 Nov 2022 14:58:03 -0700
Subject: [PATCH 078/100] loading indicator and delay

---
 .../desktop_delete_wallet_dialog.dart         | 39 +++++++++++++++++--
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
index 087629673..6729d33b9 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
@@ -13,6 +13,7 @@ import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 
 import '../../../../../providers/desktop/storage_crypto_handler_provider.dart';
@@ -177,11 +178,35 @@ class _DesktopDeleteWalletDialog
                       label: "Continue",
                       onPressed: _continueEnabled
                           ? () async {
+                              // add loading indicator
+                              unawaited(
+                                showDialog(
+                                  context: context,
+                                  builder: (context) => Column(
+                                    mainAxisAlignment: MainAxisAlignment.center,
+                                    crossAxisAlignment:
+                                        CrossAxisAlignment.center,
+                                    children: const [
+                                      LoadingIndicator(
+                                        width: 200,
+                                        height: 200,
+                                      ),
+                                    ],
+                                  ),
+                                ),
+                              );
+
+                              await Future<void>.delayed(
+                                  const Duration(seconds: 1));
+
                               final verified = await ref
                                   .read(storageCryptoHandlerProvider)
                                   .verifyPassphrase(passwordController.text);
 
                               if (verified) {
+                                Navigator.of(context, rootNavigator: true)
+                                    .pop();
+
                                 final words = await ref
                                     .read(walletsChangeNotifierProvider)
                                     .getManager(widget.walletId)
@@ -190,12 +215,20 @@ class _DesktopDeleteWalletDialog
                                 if (mounted) {
                                   Navigator.of(context).pop();
 
-                                  await Navigator.of(context).pushNamed(
-                                    DesktopAttentionDeleteWallet.routeName,
-                                    arguments: widget.walletId,
+                                  unawaited(
+                                    Navigator.of(context).pushNamed(
+                                      DesktopAttentionDeleteWallet.routeName,
+                                      arguments: widget.walletId,
+                                    ),
                                   );
                                 }
                               } else {
+                                Navigator.of(context, rootNavigator: true)
+                                    .pop();
+
+                                await Future<void>.delayed(
+                                    const Duration(milliseconds: 300));
+
                                 unawaited(
                                   showFloatingFlushBar(
                                     type: FlushBarType.warning,

From c935c590c7c5635487503e4587f34d94e8f0ae77 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Mon, 21 Nov 2022 16:00:00 -0600
Subject: [PATCH 079/100] desktop exchange flow tweaks and show QR code

---
 lib/pages/exchange_view/exchange_form.dart    |  2 +
 .../subwidgets/desktop_step_1.dart            |  1 +
 .../subwidgets/desktop_step_2.dart            | 30 +++++++--
 .../subwidgets/desktop_step_3.dart            | 67 ++++++++++++-------
 .../subwidgets/desktop_step_4.dart            | 49 +++++++++++++-
 .../subwidgets/desktop_step_item.dart         |  1 +
 .../subwidgets/desktop_trade_history.dart     |  2 +
 7 files changed, 121 insertions(+), 31 deletions(-)

diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart
index 7faa83a35..7f0d9b5d2 100644
--- a/lib/pages/exchange_view/exchange_form.dart
+++ b/lib/pages/exchange_view/exchange_form.dart
@@ -1024,6 +1024,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
         if (isDesktop) {
           await showDialog<void>(
             context: context,
+            barrierDismissible: false,
             builder: (context) {
               return DesktopDialog(
                 maxWidth: 720,
@@ -1052,6 +1053,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
         if (isDesktop) {
           await showDialog<void>(
             context: context,
+            barrierDismissible: false,
             builder: (context) {
               return DesktopDialog(
                 maxWidth: 720,
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
index a97b722ef..031dc0649 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_1.dart
@@ -104,6 +104,7 @@ class DesktopStep1 extends ConsumerWidget {
                     await showDialog<void>(
                       context: context,
                       barrierColor: Colors.transparent,
+                      barrierDismissible: false,
                       builder: (context) {
                         return DesktopDialog(
                           maxWidth: 720,
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
index 270b98fc7..525d561fc 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
@@ -1,7 +1,10 @@
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:stackwallet/models/contact_address_entry.dart';
 import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_choose_from_stack.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart';
 import 'package:stackwallet/providers/exchange/exchange_send_from_wallet_id_provider.dart';
@@ -13,6 +16,8 @@ import 'package:stackwallet/utilities/logger.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/icon_widgets/addressbook_icon.dart';
@@ -22,10 +27,6 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 import 'package:stackwallet/widgets/textfield_icon_button.dart';
 
-import '../../../../models/contact_address_entry.dart';
-import '../../../../widgets/desktop/desktop_dialog.dart';
-import '../../../../widgets/desktop/desktop_dialog_close_button.dart';
-
 class DesktopStep2 extends ConsumerStatefulWidget {
   const DesktopStep2({
     Key? key,
@@ -552,8 +553,25 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
                 child: PrimaryButton(
                   label: "Next",
                   buttonHeight: ButtonHeight.l,
-                  onPressed: () {
-                    // todo
+                  onPressed: () async {
+                    await showDialog<void>(
+                      context: context,
+                      barrierColor: Colors.transparent,
+                      barrierDismissible: false,
+                      builder: (context) {
+                        return DesktopDialog(
+                          maxWidth: 720,
+                          maxHeight: double.infinity,
+                          child: StepScaffold(
+                            step: 3,
+                            model: model,
+                            body: DesktopStep3(
+                              model: model,
+                            ),
+                          ),
+                        );
+                      },
+                    );
                   },
                 ),
               ),
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
index 65b6ed2b3..284416545 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_3.dart
@@ -4,8 +4,9 @@ import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
 import 'package:stackwallet/models/exchange/response_objects/trade.dart';
-import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_4_view.dart';
 import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
 import 'package:stackwallet/providers/exchange/current_exchange_name_state_provider.dart';
 import 'package:stackwallet/providers/exchange/exchange_provider.dart';
@@ -16,10 +17,11 @@ import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/custom_loading_overlay.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/desktop/simple_desktop_dialog.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
-import 'package:stackwallet/widgets/stack_dialog.dart';
 
 class DesktopStep3 extends ConsumerStatefulWidget {
   const DesktopStep3({
@@ -76,14 +78,15 @@ class _DesktopStep3State extends ConsumerState<DesktopStep3> {
         Navigator.of(context).pop();
       }
 
-      unawaited(showDialog<void>(
-        context: context,
-        barrierDismissible: true,
-        builder: (_) => StackDialog(
-          title: "Failed to create trade",
-          message: response.exception?.toString(),
+      unawaited(
+        showDialog<void>(
+          context: context,
+          barrierDismissible: true,
+          builder: (_) => SimpleDesktopDialog(
+              title: "Failed to create trade",
+              message: response.exception?.toString() ?? ""),
         ),
-      ));
+      );
       return;
     }
 
@@ -106,22 +109,40 @@ class _DesktopStep3State extends ConsumerState<DesktopStep3> {
       Navigator.of(context).pop();
     }
 
-    unawaited(NotificationApi.showNotification(
-      changeNowId: model.trade!.tradeId,
-      title: status,
-      body: "Trade ID ${model.trade!.tradeId}",
-      walletId: "",
-      iconAssetName: Assets.svg.arrowRotate,
-      date: model.trade!.timestamp,
-      shouldWatchForUpdates: true,
-      coinName: "coinName",
-    ));
+    unawaited(
+      NotificationApi.showNotification(
+        changeNowId: model.trade!.tradeId,
+        title: status,
+        body: "Trade ID ${model.trade!.tradeId}",
+        walletId: "",
+        iconAssetName: Assets.svg.arrowRotate,
+        date: model.trade!.timestamp,
+        shouldWatchForUpdates: true,
+        coinName: "coinName",
+      ),
+    );
 
     if (mounted) {
-      unawaited(Navigator.of(context).pushNamed(
-        Step4View.routeName,
-        arguments: model,
-      ));
+      unawaited(
+        showDialog<void>(
+          context: context,
+          barrierColor: Colors.transparent,
+          barrierDismissible: false,
+          builder: (context) {
+            return DesktopDialog(
+              maxWidth: 720,
+              maxHeight: double.infinity,
+              child: StepScaffold(
+                step: 4,
+                model: model,
+                body: DesktopStep4(
+                  model: model,
+                ),
+              ),
+            );
+          },
+        ),
+      );
     }
   }
 
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
index ba9838086..7747f570f 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
@@ -2,12 +2,14 @@ import 'dart:async';
 
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:qr_flutter/qr_flutter.dart';
 import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
 import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/rounded_container.dart';
@@ -148,7 +150,7 @@ class _DesktopStep4State extends ConsumerState<DesktopStep4> {
               DesktopStepItem(
                 label: "Amount",
                 value:
-                    "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}",
+                    "${model.sendAmount.toStringAsFixed(8)} ${model.sendTicker.toUpperCase()}",
               ),
               Container(
                 height: 1,
@@ -208,7 +210,50 @@ class _DesktopStep4State extends ConsumerState<DesktopStep4> {
                   label: "Show QR code",
                   buttonHeight: ButtonHeight.l,
                   onPressed: () {
-                    // todo
+                    showDialog<dynamic>(
+                      context: context,
+                      barrierColor: Colors.transparent,
+                      barrierDismissible: true,
+                      builder: (_) {
+                        return DesktopDialog(
+                          maxHeight: 720,
+                          maxWidth: 720,
+                          child: Column(
+                            mainAxisAlignment: MainAxisAlignment.center,
+                            crossAxisAlignment: CrossAxisAlignment.center,
+                            children: [
+                              Text(
+                                "Send ${model.sendAmount.toStringAsFixed(8)} ${model.sendTicker} to this address",
+                                style: STextStyles.desktopH3(context),
+                              ),
+                              const SizedBox(
+                                height: 48,
+                              ),
+                              Center(
+                                child: QrImage(
+                                  // TODO: grab coin uri scheme from somewhere
+                                  // data: "${coin.uriScheme}:$receivingAddress",
+                                  data: model.trade!.payInAddress,
+                                  size: 290,
+                                  foregroundColor: Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .accentColorDark,
+                                ),
+                              ),
+                              const SizedBox(
+                                height: 48,
+                              ),
+                              SecondaryButton(
+                                label: "Cancel",
+                                width: 310,
+                                buttonHeight: ButtonHeight.l,
+                                onPressed: Navigator.of(context).pop,
+                              ),
+                            ],
+                          ),
+                        );
+                      },
+                    );
                   },
                 ),
               ),
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart
index 7c777c2dd..323517e13 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart
@@ -24,6 +24,7 @@ class DesktopStepItem extends StatelessWidget {
       child: ConditionalParent(
         condition: vertical,
         builder: (child) => Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
           children: [
             child,
             const SizedBox(
diff --git a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
index 40eeb8c1b..41bf4246a 100644
--- a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
@@ -31,6 +31,8 @@ class _DesktopTradeHistoryState extends ConsumerState<DesktopTradeHistory> {
 
     if (hasHistory) {
       return ListView.separated(
+        shrinkWrap: true,
+        primary: false,
         itemBuilder: (context, index) {
           return TradeCard(
             key: Key("tradeCard_${trades[index].uuid}"),

From a10958b12d02f0073354cb4402504f46ec75efa9 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Mon, 21 Nov 2022 15:08:31 -0700
Subject: [PATCH 080/100] delete popup rounded corner fix

---
 .../wallet_view/sub_widgets/delete_wallet_button.dart           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
index f2553c2da..a2071e7d6 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart
@@ -127,7 +127,7 @@ class _DeletePopupButtonState extends State<DeletePopupButton> {
                 height: 70,
                 decoration: BoxDecoration(
                   borderRadius: BorderRadius.circular(
-                    Constants.size.circularBorderRadius,
+                    Constants.size.circularBorderRadius * 2,
                   ),
                   color: Theme.of(context).extension<StackColors>()!.popupBG,
                   boxShadow: [

From 7a650c78d39006620e6ba4f96069feb42f6e1153 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Mon, 21 Nov 2022 15:17:26 -0700
Subject: [PATCH 081/100] loading indicator and delay for wallet keys

---
 .../unlock_wallet_keys_desktop.dart           | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart
index 23360c98c..739a3ebc4 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart
@@ -16,6 +16,7 @@ import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 
 class UnlockWalletKeysDesktop extends ConsumerStatefulWidget {
@@ -201,11 +202,32 @@ class _UnlockWalletKeysDesktopState
                     enabled: continueEnabled,
                     onPressed: continueEnabled
                         ? () async {
+                            unawaited(
+                              showDialog(
+                                context: context,
+                                builder: (context) => Column(
+                                  mainAxisAlignment: MainAxisAlignment.center,
+                                  crossAxisAlignment: CrossAxisAlignment.center,
+                                  children: const [
+                                    LoadingIndicator(
+                                      width: 200,
+                                      height: 200,
+                                    ),
+                                  ],
+                                ),
+                              ),
+                            );
+
+                            await Future<void>.delayed(
+                                const Duration(seconds: 1));
+
                             final verified = await ref
                                 .read(storageCryptoHandlerProvider)
                                 .verifyPassphrase(passwordController.text);
 
                             if (verified) {
+                              Navigator.of(context, rootNavigator: true).pop();
+
                               final words = await ref
                                   .read(walletsChangeNotifierProvider)
                                   .getManager(widget.walletId)
@@ -219,6 +241,11 @@ class _UnlockWalletKeysDesktopState
                                 );
                               }
                             } else {
+                              Navigator.of(context, rootNavigator: true).pop();
+
+                              await Future<void>.delayed(
+                                  const Duration(milliseconds: 300));
+
                               unawaited(
                                 showFloatingFlushBar(
                                   type: FlushBarType.warning,

From 675977c787d9d987819852199fefe32882e7bfe6 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Mon, 21 Nov 2022 20:33:38 -0700
Subject: [PATCH 082/100] copy to clipboard added to wallet keys dialog

---
 .../sub_widgets/delete_wallet_keys_popup.dart | 40 ++++++++++++++++---
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
index 6b638bb75..70f4a3e13 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart
@@ -1,9 +1,15 @@
+import 'dart:async';
+
 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:stackwallet/notifications/show_flush_bar.dart';
 import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart';
 import 'package:stackwallet/providers/global/wallets_provider.dart';
 import 'package:stackwallet/providers/global/wallets_service_provider.dart';
 import 'package:stackwallet/route_generator.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/clipboard_interface.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
@@ -16,10 +22,12 @@ class DeleteWalletKeysPopup extends ConsumerStatefulWidget {
     Key? key,
     required this.walletId,
     required this.words,
+    this.clipboardInterface = const ClipboardWrapper(),
   }) : super(key: key);
 
   final String walletId;
   final List<String> words;
+  final ClipboardInterface clipboardInterface;
 
   static const String routeName = "/desktopDeleteWalletKeysPopup";
 
@@ -30,10 +38,14 @@ class DeleteWalletKeysPopup extends ConsumerStatefulWidget {
 
 class _DeleteWalletKeysPopup extends ConsumerState<DeleteWalletKeysPopup> {
   late final String _walletId;
+  late final List<String> _words;
+  late final ClipboardInterface _clipboardInterface;
 
   @override
   void initState() {
     _walletId = widget.walletId;
+    _words = widget.words;
+    _clipboardInterface = widget.clipboardInterface;
 
     super.initState();
   }
@@ -96,12 +108,28 @@ class _DeleteWalletKeysPopup extends ConsumerState<DeleteWalletKeysPopup> {
             padding: const EdgeInsets.symmetric(
               horizontal: 32,
             ),
-            child: MnemonicTable(
-              words: widget.words,
-              isDesktop: true,
-              itemBorderColor: Theme.of(context)
-                  .extension<StackColors>()!
-                  .buttonBackSecondary,
+            child: RawMaterialButton(
+              hoverColor: Colors.transparent,
+              onPressed: () async {
+                await _clipboardInterface.setData(
+                  ClipboardData(text: _words.join(" ")),
+                );
+                unawaited(
+                  showFloatingFlushBar(
+                    type: FlushBarType.info,
+                    message: "Copied to clipboard",
+                    iconAsset: Assets.svg.copy,
+                    context: context,
+                  ),
+                );
+              },
+              child: MnemonicTable(
+                words: widget.words,
+                isDesktop: true,
+                itemBorderColor: Theme.of(context)
+                    .extension<StackColors>()!
+                    .buttonBackSecondary,
+              ),
             ),
           ),
           const SizedBox(

From 6384d66308066645500f516eca9784163a8285d0 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Mon, 21 Nov 2022 20:34:36 -0700
Subject: [PATCH 083/100] added delays for floatingFlushBar in settings change
 password

---
 .../home/settings_menu/security_settings.dart             | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lib/pages_desktop_specific/home/settings_menu/security_settings.dart b/lib/pages_desktop_specific/home/settings_menu/security_settings.dart
index f6762afa1..ff7537126 100644
--- a/lib/pages_desktop_specific/home/settings_menu/security_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/security_settings.dart
@@ -61,6 +61,8 @@ class _SecuritySettings extends ConsumerState<SecuritySettings> {
 
     if (verified) {
       if (pwNew != pwNewRepeat) {
+        await Future<void>.delayed(const Duration(seconds: 1));
+
         unawaited(
           showFloatingFlushBar(
             type: FlushBarType.warning,
@@ -77,6 +79,8 @@ class _SecuritySettings extends ConsumerState<SecuritySettings> {
                 );
 
         if (success) {
+          await Future<void>.delayed(const Duration(seconds: 1));
+
           unawaited(
             showFloatingFlushBar(
               type: FlushBarType.success,
@@ -86,6 +90,8 @@ class _SecuritySettings extends ConsumerState<SecuritySettings> {
           );
           return true;
         } else {
+          await Future<void>.delayed(const Duration(seconds: 1));
+
           unawaited(
             showFloatingFlushBar(
               type: FlushBarType.warning,
@@ -97,6 +103,8 @@ class _SecuritySettings extends ConsumerState<SecuritySettings> {
         }
       }
     } else {
+      await Future<void>.delayed(const Duration(seconds: 1));
+
       unawaited(
         showFloatingFlushBar(
           type: FlushBarType.warning,

From b32e15a3ea1176eb4f77920fa97b46f1d95c3828 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 07:13:03 -0600
Subject: [PATCH 084/100] desktop login on enter pressed

---
 lib/pages_desktop_specific/desktop_login_view.dart | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lib/pages_desktop_specific/desktop_login_view.dart b/lib/pages_desktop_specific/desktop_login_view.dart
index f865fad47..eb5dec18a 100644
--- a/lib/pages_desktop_specific/desktop_login_view.dart
+++ b/lib/pages_desktop_specific/desktop_login_view.dart
@@ -165,6 +165,12 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
                     obscureText: hidePassword,
                     enableSuggestions: false,
                     autocorrect: false,
+                    autofocus: true,
+                    onSubmitted: (_) {
+                      if (_continueEnabled) {
+                        login();
+                      }
+                    },
                     decoration: standardInputDecoration(
                       "Enter password",
                       passwordFocusNode,

From b512b2cefb4663a0075b749c2cc2d4126060717b Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 07:15:08 -0600
Subject: [PATCH 085/100] consistent decimal places on firo balance selection
 sheet

---
 .../firo_balance_selection_sheet.dart         |  4 ++--
 .../wallet_balance_toggle_sheet.dart          | 11 ++++-----
 lib/utilities/constants.dart                  | 24 +++++++++++++++++++
 3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart b/lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart
index e639a8cf8..d6de3c6ee 100644
--- a/lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart
+++ b/lib/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart
@@ -161,7 +161,7 @@ class _FiroBalanceSelectionSheetState
                                           ConnectionState.done &&
                                       snapshot.hasData) {
                                     return Text(
-                                      "${snapshot.data!} ${manager.coin.ticker}",
+                                      "${snapshot.data!.toStringAsFixed(8)} ${manager.coin.ticker}",
                                       style: STextStyles.itemSubtitle(context),
                                       textAlign: TextAlign.left,
                                     );
@@ -251,7 +251,7 @@ class _FiroBalanceSelectionSheetState
                                           ConnectionState.done &&
                                       snapshot.hasData) {
                                     return Text(
-                                      "${snapshot.data!} ${manager.coin.ticker}",
+                                      "${snapshot.data!.toStringAsFixed(8)} ${manager.coin.ticker}",
                                       style: STextStyles.itemSubtitle(context),
                                       textAlign: TextAlign.left,
                                     );
diff --git a/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart b/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart
index c9ff64393..74308f2e8 100644
--- a/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart
+++ b/lib/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart
@@ -3,14 +3,13 @@ import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.dart';
+import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
 import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 
-import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
-
 class WalletBalanceToggleSheet extends ConsumerWidget {
   const WalletBalanceToggleSheet({
     Key? key,
@@ -153,7 +152,7 @@ class WalletBalanceToggleSheet extends ConsumerWidget {
                                       snapshot.hasData &&
                                       snapshot.data != null) {
                                     return Text(
-                                      "${snapshot.data!}",
+                                      "${snapshot.data!.toStringAsFixed(Constants.decimalPlacesForCoin(coin))} ${coin.ticker}",
                                       style: STextStyles.itemSubtitle12(context)
                                           .copyWith(
                                         color: Theme.of(context)
@@ -195,7 +194,7 @@ class WalletBalanceToggleSheet extends ConsumerWidget {
                                       snapshot.hasData &&
                                       snapshot.data != null) {
                                     return Text(
-                                      "${snapshot.data!}",
+                                      "${snapshot.data!.toStringAsFixed(Constants.decimalPlacesForCoin(coin))} ${coin.ticker}",
                                       style: STextStyles.itemSubtitle12(context)
                                           .copyWith(
                                         color: Theme.of(context)
@@ -287,7 +286,7 @@ class WalletBalanceToggleSheet extends ConsumerWidget {
                                       snapshot.hasData &&
                                       snapshot.data != null) {
                                     return Text(
-                                      "${snapshot.data!}",
+                                      "${snapshot.data!.toStringAsFixed(Constants.decimalPlacesForCoin(coin))} ${coin.ticker}",
                                       style: STextStyles.itemSubtitle12(context)
                                           .copyWith(
                                         color: Theme.of(context)
@@ -329,7 +328,7 @@ class WalletBalanceToggleSheet extends ConsumerWidget {
                                       snapshot.hasData &&
                                       snapshot.data != null) {
                                     return Text(
-                                      "${snapshot.data!}",
+                                      "${snapshot.data!.toStringAsFixed(Constants.decimalPlacesForCoin(coin))} ${coin.ticker}",
                                       style: STextStyles.itemSubtitle12(context)
                                           .copyWith(
                                         color: Theme.of(context)
diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart
index e27fbaa3d..0a062de67 100644
--- a/lib/utilities/constants.dart
+++ b/lib/utilities/constants.dart
@@ -40,6 +40,30 @@ abstract class Constants {
 
   static const int currentHiveDbVersion = 3;
 
+  static int decimalPlacesForCoin(Coin coin) {
+    switch (coin) {
+      case Coin.bitcoin:
+      case Coin.litecoin:
+      case Coin.litecoinTestNet:
+      case Coin.bitcoincash:
+      case Coin.bitcoincashTestnet:
+      case Coin.dogecoin:
+      case Coin.firo:
+      case Coin.bitcoinTestNet:
+      case Coin.dogecoinTestNet:
+      case Coin.firoTestNet:
+      case Coin.epicCash:
+      case Coin.namecoin:
+        return decimalPlaces;
+
+      case Coin.wownero:
+        return decimalPlacesWownero;
+
+      case Coin.monero:
+        return decimalPlacesMonero;
+    }
+  }
+
   static List<int> possibleLengthsForCoin(Coin coin) {
     final List<int> values = [];
     switch (coin) {

From 7afe6940f9dc5f20f08eb59e606d8e4cbb452cd4 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 08:07:22 -0600
Subject: [PATCH 086/100] desktop trade history details updated

---
 .../exchange_view/trade_details_view.dart     | 186 ++++++++++++++----
 .../subwidgets/desktop_trade_history.dart     | 124 +++++++++++-
 lib/widgets/trade_card.dart                   | 134 +++++++------
 3 files changed, 335 insertions(+), 109 deletions(-)

diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart
index 602d588da..f28d1d617 100644
--- a/lib/pages/exchange_view/trade_details_view.dart
+++ b/lib/pages/exchange_view/trade_details_view.dart
@@ -206,16 +206,57 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
               padding: const EdgeInsets.only(
                 right: 12,
               ),
-              child: RoundedWhiteContainer(
-                borderColor: isDesktop
-                    ? Theme.of(context).extension<StackColors>()!.background
-                    : null,
-                padding: const EdgeInsets.all(0),
-                child: ListView(
-                  primary: false,
-                  shrinkWrap: true,
-                  children: children,
-                ),
+              child: Column(
+                mainAxisSize: MainAxisSize.min,
+                children: [
+                  RoundedWhiteContainer(
+                    borderColor:
+                        Theme.of(context).extension<StackColors>()!.background,
+                    padding: const EdgeInsets.all(0),
+                    child: ListView(
+                      primary: false,
+                      shrinkWrap: true,
+                      children: children,
+                    ),
+                  ),
+                  if (isStackCoin(trade.payInCurrency) &&
+                      (trade.status == "New" ||
+                          trade.status == "new" ||
+                          trade.status == "waiting" ||
+                          trade.status == "Waiting"))
+                    const SizedBox(
+                      height: 32,
+                    ),
+                  if (isStackCoin(trade.payInCurrency) &&
+                      (trade.status == "New" ||
+                          trade.status == "new" ||
+                          trade.status == "waiting" ||
+                          trade.status == "Waiting"))
+                    SecondaryButton(
+                      label: "Send from Stack",
+                      buttonHeight: ButtonHeight.l,
+                      onPressed: () {
+                        final amount = sendAmount;
+                        final address = trade.payInAddress;
+
+                        final coin =
+                            coinFromTickerCaseInsensitive(trade.payInCurrency);
+
+                        Navigator.of(context).pushNamed(
+                          SendFromView.routeName,
+                          arguments: Tuple4(
+                            coin,
+                            amount,
+                            address,
+                            trade,
+                          ),
+                        );
+                      },
+                    ),
+                  const SizedBox(
+                    height: 32,
+                  ),
+                ],
               ),
             ),
           ),
@@ -350,33 +391,94 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
                 padding: isDesktop
                     ? const EdgeInsets.all(16)
                     : const EdgeInsets.all(12),
-                color: Theme.of(context)
-                    .extension<StackColors>()!
-                    .warningBackground,
-                child: RichText(
-                  text: TextSpan(
-                      text:
-                          "You must send at least ${sendAmount.toStringAsFixed(
-                        trade.payInCurrency.toLowerCase() == "xmr" ? 12 : 8,
-                      )} ${trade.payInCurrency.toUpperCase()}. ",
-                      style: STextStyles.label700(context).copyWith(
-                        color: Theme.of(context)
-                            .extension<StackColors>()!
-                            .warningForeground,
-                      ),
-                      children: [
-                        TextSpan(
-                          text:
-                              "If you send less than ${sendAmount.toStringAsFixed(
-                            trade.payInCurrency.toLowerCase() == "xmr" ? 12 : 8,
-                          )} ${trade.payInCurrency.toUpperCase()}, your transaction may not be converted and it may not be refunded.",
-                          style: STextStyles.label(context).copyWith(
-                            color: Theme.of(context)
-                                .extension<StackColors>()!
-                                .warningForeground,
+                color: isDesktop
+                    ? Theme.of(context).extension<StackColors>()!.popupBG
+                    : Theme.of(context)
+                        .extension<StackColors>()!
+                        .warningBackground,
+                child: ConditionalParent(
+                  condition: isDesktop,
+                  builder: (child) => Column(
+                    mainAxisSize: MainAxisSize.min,
+                    children: [
+                      Row(
+                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: [
+                          Column(
+                            crossAxisAlignment: CrossAxisAlignment.start,
+                            children: [
+                              Text(
+                                "Amount",
+                                style: STextStyles.desktopTextExtraExtraSmall(
+                                    context),
+                              ),
+                              const SizedBox(
+                                height: 2,
+                              ),
+                              Text(
+                                "${trade.payInAmount} ${trade.payInCurrency.toUpperCase()}",
+                                style: STextStyles.desktopTextExtraExtraSmall(
+                                        context)
+                                    .copyWith(
+                                  color: Theme.of(context)
+                                      .extension<StackColors>()!
+                                      .textDark,
+                                ),
+                              ),
+                            ],
                           ),
-                        ),
-                      ]),
+                          IconCopyButton(
+                            data: trade.payInAmount,
+                          ),
+                        ],
+                      ),
+                      const SizedBox(
+                        height: 6,
+                      ),
+                      child,
+                    ],
+                  ),
+                  child: RichText(
+                    text: TextSpan(
+                        text:
+                            "You must send at least ${sendAmount.toStringAsFixed(
+                          trade.payInCurrency.toLowerCase() == "xmr" ? 12 : 8,
+                        )} ${trade.payInCurrency.toUpperCase()}. ",
+                        style: isDesktop
+                            ? STextStyles.desktopTextExtraExtraSmall(context)
+                                .copyWith(
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .accentColorRed)
+                            : STextStyles.label(context).copyWith(
+                                color: Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .warningForeground,
+                              ),
+                        children: [
+                          TextSpan(
+                            text:
+                                "If you send less than ${sendAmount.toStringAsFixed(
+                              trade.payInCurrency.toLowerCase() == "xmr"
+                                  ? 12
+                                  : 8,
+                            )} ${trade.payInCurrency.toUpperCase()}, your transaction may not be converted and it may not be refunded.",
+                            style: isDesktop
+                                ? STextStyles.desktopTextExtraExtraSmall(
+                                        context)
+                                    .copyWith(
+                                        color: Theme.of(context)
+                                            .extension<StackColors>()!
+                                            .accentColorRed)
+                                : STextStyles.label(context).copyWith(
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .warningForeground,
+                                  ),
+                          ),
+                        ]),
+                  ),
                 ),
               ),
             if (sentFromStack)
@@ -1035,12 +1137,12 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
                 ],
               ),
             ),
-            isDesktop
-                ? const _Divider()
-                : const SizedBox(
-                    height: 12,
-                  ),
-            if (isStackCoin(trade.payInCurrency) &&
+            if (!isDesktop)
+              const SizedBox(
+                height: 12,
+              ),
+            if (!isDesktop &&
+                isStackCoin(trade.payInCurrency) &&
                 (trade.status == "New" ||
                     trade.status == "new" ||
                     trade.status == "waiting" ||
diff --git a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
index 41bf4246a..a8f825911 100644
--- a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
@@ -10,7 +10,10 @@ import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/trade_card.dart';
-import 'package:tuple/tuple.dart';
+
+import '../../../route_generator.dart';
+import '../../../widgets/desktop/desktop_dialog.dart';
+import '../../../widgets/desktop/desktop_dialog_close_button.dart';
 
 class DesktopTradeHistory extends ConsumerStatefulWidget {
   const DesktopTradeHistory({Key? key}) : super(key: key);
@@ -64,19 +67,122 @@ class _DesktopTradeHistoryState extends ConsumerState<DesktopTradeHistory> {
                 final tx = txData.getAllTransactions()[txid];
 
                 if (mounted) {
-                  unawaited(
-                    Navigator.of(context).pushNamed(
-                      TradeDetailsView.routeName,
-                      arguments: Tuple4(
-                          tradeId, tx, walletIds.first, manager.walletName),
+                  await showDialog<void>(
+                    context: context,
+                    builder: (context) => Navigator(
+                      initialRoute: TradeDetailsView.routeName,
+                      onGenerateRoute: RouteGenerator.generateRoute,
+                      onGenerateInitialRoutes: (_, __) {
+                        return [
+                          FadePageRoute(
+                            DesktopDialog(
+                              // maxHeight:
+                              //     MediaQuery.of(context).size.height - 64,
+                              maxHeight: double.infinity,
+                              maxWidth: 580,
+                              child: Column(
+                                mainAxisSize: MainAxisSize.min,
+                                children: [
+                                  Padding(
+                                    padding: const EdgeInsets.only(
+                                      left: 32,
+                                      bottom: 16,
+                                    ),
+                                    child: Row(
+                                      mainAxisAlignment:
+                                          MainAxisAlignment.spaceBetween,
+                                      children: [
+                                        Text(
+                                          "Trade details",
+                                          style: STextStyles.desktopH3(context),
+                                        ),
+                                        DesktopDialogCloseButton(
+                                          onPressedOverride: Navigator.of(
+                                            context,
+                                            rootNavigator: true,
+                                          ).pop,
+                                        ),
+                                      ],
+                                    ),
+                                  ),
+                                  Flexible(
+                                    child: TradeDetailsView(
+                                      tradeId: tradeId,
+                                      transactionIfSentFromStack: tx,
+                                      walletName: manager.walletName,
+                                      walletId: walletIds.first,
+                                    ),
+                                  ),
+                                ],
+                              ),
+                            ),
+                            const RouteSettings(
+                              name: TradeDetailsView.routeName,
+                            ),
+                          ),
+                        ];
+                      },
                     ),
                   );
                 }
               } else {
                 unawaited(
-                  Navigator.of(context).pushNamed(
-                    TradeDetailsView.routeName,
-                    arguments: Tuple4(tradeId, null, walletIds?.first, null),
+                  showDialog<void>(
+                    context: context,
+                    builder: (context) => Navigator(
+                      initialRoute: TradeDetailsView.routeName,
+                      onGenerateRoute: RouteGenerator.generateRoute,
+                      onGenerateInitialRoutes: (_, __) {
+                        return [
+                          FadePageRoute(
+                            DesktopDialog(
+                              // maxHeight:
+                              //     MediaQuery.of(context).size.height - 64,
+                              maxHeight: double.infinity,
+                              maxWidth: 580,
+                              child: Column(
+                                mainAxisSize: MainAxisSize.min,
+                                children: [
+                                  Padding(
+                                    padding: const EdgeInsets.only(
+                                      left: 32,
+                                      bottom: 16,
+                                    ),
+                                    child: Row(
+                                      mainAxisAlignment:
+                                          MainAxisAlignment.spaceBetween,
+                                      children: [
+                                        Text(
+                                          "Trade details",
+                                          style: STextStyles.desktopH3(context),
+                                        ),
+                                        DesktopDialogCloseButton(
+                                          onPressedOverride: Navigator.of(
+                                            context,
+                                            rootNavigator: true,
+                                          ).pop,
+                                        ),
+                                      ],
+                                    ),
+                                  ),
+                                  Flexible(
+                                    child: TradeDetailsView(
+                                      tradeId: tradeId,
+                                      transactionIfSentFromStack: null,
+                                      walletName: null,
+                                      walletId: walletIds?.first,
+                                    ),
+                                  ),
+                                ],
+                              ),
+                            ),
+                            const RouteSettings(
+                              name: TradeDetailsView.routeName,
+                            ),
+                          ),
+                        ];
+                      },
+                    ),
                   ),
                 );
               }
diff --git a/lib/widgets/trade_card.dart b/lib/widgets/trade_card.dart
index 0ac8e9346..5a14a0777 100644
--- a/lib/widgets/trade_card.dart
+++ b/lib/widgets/trade_card.dart
@@ -8,6 +8,7 @@ import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/format.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 
 class TradeCard extends ConsumerWidget {
@@ -49,68 +50,85 @@ class TradeCard extends ConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    return GestureDetector(
-      onTap: onTap,
-      child: RoundedWhiteContainer(
-        child: Row(
-          children: [
-            Container(
-              width: 32,
-              height: 32,
-              decoration: BoxDecoration(
-                borderRadius: BorderRadius.circular(32),
-              ),
-              child: Center(
-                child: SvgPicture.asset(
-                  _fetchIconAssetForStatus(
-                    trade.status,
-                    context,
+    final isDesktop = Util.isDesktop;
+
+    return ConditionalParent(
+      condition: isDesktop,
+      builder: (child) => MouseRegion(
+        cursor: SystemMouseCursors.click,
+        child: child,
+      ),
+      child: GestureDetector(
+        onTap: onTap,
+        child: RoundedWhiteContainer(
+          padding:
+              isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12),
+          child: Row(
+            children: [
+              Container(
+                width: 32,
+                height: 32,
+                decoration: BoxDecoration(
+                  borderRadius: BorderRadius.circular(32),
+                ),
+                child: Center(
+                  child: SvgPicture.asset(
+                    _fetchIconAssetForStatus(
+                      trade.status,
+                      context,
+                    ),
+                    width: 32,
+                    height: 32,
                   ),
-                  width: 32,
-                  height: 32,
                 ),
               ),
-            ),
-            const SizedBox(
-              width: 12,
-            ),
-            Expanded(
-              child: Column(
-                children: [
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                    children: [
-                      Text(
-                        "${trade.payInCurrency.toUpperCase()} → ${trade.payOutCurrency.toUpperCase()}",
-                        style: STextStyles.itemSubtitle12(context),
-                      ),
-                      Text(
-                        "${Util.isDesktop ? "-" : ""}${Decimal.tryParse(trade.payInAmount) ?? "..."} ${trade.payInCurrency.toUpperCase()}",
-                        style: STextStyles.itemSubtitle12(context),
-                      ),
-                    ],
-                  ),
-                  const SizedBox(
-                    height: 2,
-                  ),
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                    children: [
-                      Text(
-                        trade.exchangeName,
-                        style: STextStyles.label(context),
-                      ),
-                      Text(
-                        Format.extractDateFrom(
-                            trade.timestamp.millisecondsSinceEpoch ~/ 1000),
-                        style: STextStyles.label(context),
-                      ),
-                    ],
-                  ),
-                ],
+              const SizedBox(
+                width: 12,
               ),
-            )
-          ],
+              Expanded(
+                child: Column(
+                  children: [
+                    Row(
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                      children: [
+                        Text(
+                          "${trade.payInCurrency.toUpperCase()} → ${trade.payOutCurrency.toUpperCase()}",
+                          style: STextStyles.itemSubtitle12(context),
+                        ),
+                        Text(
+                          "${isDesktop ? "-" : ""}${Decimal.tryParse(trade.payInAmount) ?? "..."} ${trade.payInCurrency.toUpperCase()}",
+                          style: STextStyles.itemSubtitle12(context),
+                        ),
+                      ],
+                    ),
+                    const SizedBox(
+                      height: 2,
+                    ),
+                    Row(
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                      children: [
+                        if (!isDesktop)
+                          Text(
+                            trade.exchangeName,
+                            style: STextStyles.label(context),
+                          ),
+                        Text(
+                          Format.extractDateFrom(
+                              trade.timestamp.millisecondsSinceEpoch ~/ 1000),
+                          style: STextStyles.label(context),
+                        ),
+                        if (isDesktop)
+                          Text(
+                            trade.exchangeName,
+                            style: STextStyles.label(context),
+                          ),
+                      ],
+                    ),
+                  ],
+                ),
+              )
+            ],
+          ),
         ),
       ),
     );

From 6552fc913db3d66782eddc02c54f6eb155e7a730 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 09:11:18 -0600
Subject: [PATCH 087/100] WIP send auth for trade transactions

---
 lib/pages/exchange_view/send_from_view.dart   | 281 ++++++++++++++++--
 .../send_view/confirm_transaction_view.dart   |  17 +-
 .../sub_widgets/desktop_auth_send.dart        |  32 +-
 3 files changed, 301 insertions(+), 29 deletions(-)

diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart
index c87175955..59675e4e4 100644
--- a/lib/pages/exchange_view/send_from_view.dart
+++ b/lib/pages/exchange_view/send_from_view.dart
@@ -7,6 +7,7 @@ import 'package:flutter_svg/svg.dart';
 import 'package:stackwallet/models/exchange/response_objects/trade.dart';
 import 'package:stackwallet/pages/exchange_view/confirm_change_now_send.dart';
 import 'package:stackwallet/pages/home_view/home_view.dart';
+import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
 import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dialog.dart';
 import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/route_generator.dart';
@@ -19,13 +20,18 @@ import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
 import 'package:stackwallet/utilities/format.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
 import 'package:stackwallet/widgets/animated_text.dart';
 import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
 import 'package:stackwallet/widgets/expandable.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_dialog.dart';
 
+import '../../pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart';
+
 class SendFromView extends ConsumerStatefulWidget {
   const SendFromView({
     Key? key,
@@ -90,21 +96,68 @@ class _SendFromViewState extends ConsumerState<SendFromView> {
     final walletIds = ref.watch(walletsChangeNotifierProvider
         .select((value) => value.getWalletIdsFor(coin: coin)));
 
-    return Scaffold(
-      backgroundColor: Theme.of(context).extension<StackColors>()!.background,
-      appBar: AppBar(
-        leading: AppBarBackButton(
-          onPressed: () {
-            Navigator.of(context).pop();
-          },
+    final isDesktop = Util.isDesktop;
+
+    return ConditionalParent(
+      condition: !isDesktop,
+      builder: (child) {
+        return Scaffold(
+          backgroundColor:
+              Theme.of(context).extension<StackColors>()!.background,
+          appBar: AppBar(
+            leading: AppBarBackButton(
+              onPressed: () {
+                Navigator.of(context).pop();
+              },
+            ),
+            title: Text(
+              "Send from",
+              style: STextStyles.navBarTitle(context),
+            ),
+          ),
+          body: Padding(
+            padding: const EdgeInsets.all(16),
+            child: child,
+          ),
+        );
+      },
+      child: ConditionalParent(
+        condition: isDesktop,
+        builder: (child) => DesktopDialog(
+          maxHeight: double.infinity,
+          child: Column(
+            children: [
+              Row(
+                mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                children: [
+                  Padding(
+                    padding: const EdgeInsets.only(
+                      left: 32,
+                    ),
+                    child: Text(
+                      "Send from Stack",
+                      style: STextStyles.desktopH3(context),
+                    ),
+                  ),
+                  DesktopDialogCloseButton(
+                    onPressedOverride: Navigator.of(
+                      context,
+                      rootNavigator: false,
+                    ).pop,
+                  ),
+                ],
+              ),
+              Padding(
+                padding: const EdgeInsets.only(
+                  left: 32,
+                  right: 32,
+                  bottom: 32,
+                ),
+                child: child,
+              ),
+            ],
+          ),
         ),
-        title: Text(
-          "Send from",
-          style: STextStyles.navBarTitle(context),
-        ),
-      ),
-      body: Padding(
-        padding: const EdgeInsets.all(16),
         child: Column(
           mainAxisAlignment: MainAxisAlignment.start,
           children: [
@@ -112,15 +165,23 @@ class _SendFromViewState extends ConsumerState<SendFromView> {
               children: [
                 Text(
                   "You need to send ${formatAmount(amount, coin)} ${coin.ticker}",
-                  style: STextStyles.itemSubtitle(context),
+                  style: isDesktop
+                      ? STextStyles.desktopTextExtraExtraSmall(context)
+                      : STextStyles.itemSubtitle(context),
                 ),
               ],
             ),
             const SizedBox(
               height: 16,
             ),
-            Expanded(
+            ConditionalParent(
+              condition: !isDesktop,
+              builder: (child) => Expanded(
+                child: child,
+              ),
               child: ListView.builder(
+                primary: isDesktop ? false : null,
+                shrinkWrap: isDesktop,
                 itemCount: walletIds.length,
                 itemBuilder: (context, index) {
                   return Padding(
@@ -339,10 +400,67 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
                     Constants.size.circularBorderRadius,
                   ),
                 ),
-                onPressed: () => _send(
-                  manager,
-                  shouldSendPublicFiroFunds: false,
-                ),
+                onPressed: () async {
+                  final dynamic unlocked;
+
+                  if (Util.isDesktop) {
+                    unlocked = await showDialog<bool?>(
+                      context: context,
+                      builder: (context) => DesktopDialog(
+                        maxWidth: 580,
+                        maxHeight: double.infinity,
+                        child: Column(
+                          mainAxisSize: MainAxisSize.min,
+                          children: [
+                            Row(
+                              mainAxisAlignment: MainAxisAlignment.end,
+                              children: const [
+                                DesktopDialogCloseButton(),
+                              ],
+                            ),
+                            const Padding(
+                              padding: EdgeInsets.only(
+                                left: 32,
+                                right: 32,
+                                bottom: 32,
+                              ),
+                              child: DesktopAuthSend(),
+                            ),
+                          ],
+                        ),
+                      ),
+                    );
+                  } else {
+                    unlocked = await Navigator.push(
+                      context,
+                      RouteGenerator.getRoute(
+                        shouldUseMaterialRoute:
+                            RouteGenerator.useMaterialPageRoute,
+                        builder: (_) => const LockscreenView(
+                          showBackButton: true,
+                          popOnSuccess: true,
+                          routeOnSuccessArguments: true,
+                          routeOnSuccess: "",
+                          biometricsCancelButtonString: "CANCEL",
+                          biometricsLocalizedReason:
+                              "Authenticate to send transaction",
+                          biometricsAuthenticationTitle: "Confirm Transaction",
+                        ),
+                        settings:
+                            const RouteSettings(name: "/confirmsendlockscreen"),
+                      ),
+                    );
+                  }
+
+                  if (unlocked is bool && unlocked && mounted) {
+                    unawaited(
+                      _send(
+                        manager,
+                        shouldSendPublicFiroFunds: false,
+                      ),
+                    );
+                  }
+                },
                 child: Container(
                   color: Colors.transparent,
                   child: Padding(
@@ -418,10 +536,67 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
                     Constants.size.circularBorderRadius,
                   ),
                 ),
-                onPressed: () => _send(
-                  manager,
-                  shouldSendPublicFiroFunds: true,
-                ),
+                onPressed: () async {
+                  final dynamic unlocked;
+
+                  if (Util.isDesktop) {
+                    unlocked = await showDialog<bool?>(
+                      context: context,
+                      builder: (context) => DesktopDialog(
+                        maxWidth: 580,
+                        maxHeight: double.infinity,
+                        child: Column(
+                          mainAxisSize: MainAxisSize.min,
+                          children: [
+                            Row(
+                              mainAxisAlignment: MainAxisAlignment.end,
+                              children: const [
+                                DesktopDialogCloseButton(),
+                              ],
+                            ),
+                            const Padding(
+                              padding: EdgeInsets.only(
+                                left: 32,
+                                right: 32,
+                                bottom: 32,
+                              ),
+                              child: DesktopAuthSend(),
+                            ),
+                          ],
+                        ),
+                      ),
+                    );
+                  } else {
+                    unlocked = await Navigator.push(
+                      context,
+                      RouteGenerator.getRoute(
+                        shouldUseMaterialRoute:
+                            RouteGenerator.useMaterialPageRoute,
+                        builder: (_) => const LockscreenView(
+                          showBackButton: true,
+                          popOnSuccess: true,
+                          routeOnSuccessArguments: true,
+                          routeOnSuccess: "",
+                          biometricsCancelButtonString: "CANCEL",
+                          biometricsLocalizedReason:
+                              "Authenticate to send transaction",
+                          biometricsAuthenticationTitle: "Confirm Transaction",
+                        ),
+                        settings:
+                            const RouteSettings(name: "/confirmsendlockscreen"),
+                      ),
+                    );
+                  }
+
+                  if (unlocked is bool && unlocked && mounted) {
+                    unawaited(
+                      _send(
+                        manager,
+                        shouldSendPublicFiroFunds: true,
+                      ),
+                    );
+                  }
+                },
                 child: Container(
                   color: Colors.transparent,
                   child: Padding(
@@ -504,7 +679,63 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
                 Constants.size.circularBorderRadius,
               ),
             ),
-            onPressed: () => _send(manager),
+            onPressed: () async {
+              final dynamic unlocked;
+
+              if (Util.isDesktop) {
+                unlocked = await showDialog<bool?>(
+                  context: context,
+                  builder: (context) => DesktopDialog(
+                    maxWidth: 580,
+                    maxHeight: double.infinity,
+                    child: Column(
+                      mainAxisSize: MainAxisSize.min,
+                      children: [
+                        Row(
+                          mainAxisAlignment: MainAxisAlignment.end,
+                          children: const [
+                            DesktopDialogCloseButton(),
+                          ],
+                        ),
+                        const Padding(
+                          padding: EdgeInsets.only(
+                            left: 32,
+                            right: 32,
+                            bottom: 32,
+                          ),
+                          child: DesktopAuthSend(),
+                        ),
+                      ],
+                    ),
+                  ),
+                );
+              } else {
+                unlocked = await Navigator.push(
+                  context,
+                  RouteGenerator.getRoute(
+                    shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute,
+                    builder: (_) => const LockscreenView(
+                      showBackButton: true,
+                      popOnSuccess: true,
+                      routeOnSuccessArguments: true,
+                      routeOnSuccess: "",
+                      biometricsCancelButtonString: "CANCEL",
+                      biometricsLocalizedReason:
+                          "Authenticate to send transaction",
+                      biometricsAuthenticationTitle: "Confirm Transaction",
+                    ),
+                    settings:
+                        const RouteSettings(name: "/confirmsendlockscreen"),
+                  ),
+                );
+              }
+
+              if (unlocked is bool && unlocked && mounted) {
+                unawaited(
+                  _send(manager),
+                );
+              }
+            },
             child: child,
           ),
           child: Row(
diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart
index 8f7afb0bb..276203804 100644
--- a/lib/pages/send_view/confirm_transaction_view.dart
+++ b/lib/pages/send_view/confirm_transaction_view.dart
@@ -37,6 +37,7 @@ class ConfirmTransactionView extends ConsumerStatefulWidget {
     required this.transactionInfo,
     required this.walletId,
     this.routeOnSuccessName = WalletView.routeName,
+    this.isTradeTransaction = false,
   }) : super(key: key);
 
   static const String routeName = "/confirmTransactionView";
@@ -44,6 +45,7 @@ class ConfirmTransactionView extends ConsumerStatefulWidget {
   final Map<String, dynamic> transactionInfo;
   final String walletId;
   final String routeOnSuccessName;
+  final bool isTradeTransaction;
 
   @override
   ConsumerState<ConfirmTransactionView> createState() =>
@@ -833,8 +835,19 @@ class _ConfirmTransactionViewState
                     );
                   }
 
-                  if (unlocked is bool && unlocked && mounted) {
-                    unawaited(_attemptSend(context));
+                  if (mounted) {
+                    if (unlocked == true) {
+                      unawaited(_attemptSend(context));
+                    } else {
+                      unawaited(
+                        showFloatingFlushBar(
+                            type: FlushBarType.warning,
+                            message: Util.isDesktop
+                                ? "Invalid passphrase"
+                                : "Invalid PIN",
+                            context: context),
+                      );
+                    }
                   }
                 },
               ),
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart
index 9f863c8a4..a8d1ea497 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart
@@ -1,3 +1,5 @@
+import 'dart:async';
+
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
@@ -10,6 +12,9 @@ import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 
+import '../../../../../notifications/show_flush_bar.dart';
+import '../../../../../widgets/loading_indicator.dart';
+
 class DesktopAuthSend extends ConsumerStatefulWidget {
   const DesktopAuthSend({Key? key}) : super(key: key);
 
@@ -155,12 +160,35 @@ class _DesktopAuthSendState extends ConsumerState<DesktopAuthSend> {
                 label: "Confirm",
                 buttonHeight: ButtonHeight.l,
                 onPressed: () async {
-                  // TODO show spinner while verifying passphrase
+                  unawaited(
+                    showDialog<void>(
+                      context: context,
+                      builder: (context) => Column(
+                        mainAxisAlignment: MainAxisAlignment.center,
+                        crossAxisAlignment: CrossAxisAlignment.center,
+                        children: const [
+                          LoadingIndicator(
+                            width: 200,
+                            height: 200,
+                          ),
+                        ],
+                      ),
+                    ),
+                  );
+
+                  await Future<void>.delayed(const Duration(seconds: 1));
 
                   final passwordIsValid = await verifyPassphrase();
 
                   if (mounted) {
-                    Navigator.of(context).pop(passwordIsValid);
+                    Navigator.of(context).pop();
+                    Navigator.of(
+                      context,
+                      rootNavigator: true,
+                    ).pop(passwordIsValid);
+                    await Future<void>.delayed(const Duration(
+                      milliseconds: 100,
+                    ));
                   }
                 },
               ),

From 0bdf337ffbeed8c7ebb8a3aa00271c6ccadbacf1 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 11:21:43 -0600
Subject: [PATCH 088/100] WIP send from stack desktop trade transaction
 navigation

---
 .../confirm_change_now_send.dart              | 842 ++++++++++++------
 lib/pages/exchange_view/send_from_view.dart   | 196 +---
 .../exchange_view/trade_details_view.dart     |   7 +-
 .../subwidgets/desktop_step_2.dart            |  92 +-
 .../subwidgets/desktop_step_4.dart            |  36 +-
 5 files changed, 700 insertions(+), 473 deletions(-)

diff --git a/lib/pages/exchange_view/confirm_change_now_send.dart b/lib/pages/exchange_view/confirm_change_now_send.dart
index e99cf2df4..9f62bd8ec 100644
--- a/lib/pages/exchange_view/confirm_change_now_send.dart
+++ b/lib/pages/exchange_view/confirm_change_now_send.dart
@@ -7,15 +7,23 @@ import 'package:stackwallet/models/trade_wallet_lookup.dart';
 import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
 import 'package:stackwallet/pages/send_view/sub_widgets/sending_transaction_dialog.dart';
 import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart';
 import 'package:stackwallet/providers/exchange/trade_sent_from_stack_lookup_provider.dart';
 import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/route_generator.dart';
 import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
+import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/format.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
 import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/rounded_container.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_dialog.dart';
@@ -52,14 +60,16 @@ class _ConfirmChangeNowSendViewState
   late final Trade trade;
 
   Future<void> _attemptSend(BuildContext context) async {
-    unawaited(showDialog<void>(
-      context: context,
-      useSafeArea: false,
-      barrierDismissible: false,
-      builder: (context) {
-        return const SendingTransactionDialog();
-      },
-    ));
+    unawaited(
+      showDialog<void>(
+        context: context,
+        useSafeArea: false,
+        barrierDismissible: false,
+        builder: (context) {
+          return const SendingTransactionDialog();
+        },
+      ),
+    );
 
     final String note = transactionInfo["note"] as String? ?? "";
     final manager =
@@ -93,6 +103,9 @@ class _ConfirmChangeNowSendViewState
 
       // pop back to wallet
       if (mounted) {
+        if (Util.isDesktop) {
+          Navigator.of(context, rootNavigator: true).pop();
+        }
         Navigator.of(context).popUntil(ModalRoute.withName(routeOnSuccessName));
       }
     } catch (e) {
@@ -129,6 +142,60 @@ class _ConfirmChangeNowSendViewState
     }
   }
 
+  Future<void> _confirmSend() async {
+    final dynamic unlocked;
+
+    if (Util.isDesktop) {
+      unlocked = await showDialog<bool?>(
+        context: context,
+        builder: (context) => DesktopDialog(
+          maxWidth: 580,
+          maxHeight: double.infinity,
+          child: Column(
+            mainAxisSize: MainAxisSize.min,
+            children: [
+              Row(
+                mainAxisAlignment: MainAxisAlignment.end,
+                children: const [
+                  DesktopDialogCloseButton(),
+                ],
+              ),
+              const Padding(
+                padding: EdgeInsets.only(
+                  left: 32,
+                  right: 32,
+                  bottom: 32,
+                ),
+                child: DesktopAuthSend(),
+              ),
+            ],
+          ),
+        ),
+      );
+    } else {
+      unlocked = await Navigator.push(
+        context,
+        RouteGenerator.getRoute(
+          shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute,
+          builder: (_) => const LockscreenView(
+            showBackButton: true,
+            popOnSuccess: true,
+            routeOnSuccessArguments: true,
+            routeOnSuccess: "",
+            biometricsCancelButtonString: "CANCEL",
+            biometricsLocalizedReason: "Authenticate to send transaction",
+            biometricsAuthenticationTitle: "Confirm Transaction",
+          ),
+          settings: const RouteSettings(name: "/confirmsendlockscreen"),
+        ),
+      );
+    }
+
+    if (unlocked is bool && unlocked && mounted) {
+      await _attemptSend(context);
+    }
+  }
+
   @override
   void initState() {
     transactionInfo = widget.transactionInfo;
@@ -142,280 +209,503 @@ class _ConfirmChangeNowSendViewState
   Widget build(BuildContext context) {
     final managerProvider = ref.watch(walletsChangeNotifierProvider
         .select((value) => value.getManagerProvider(walletId)));
-    return Scaffold(
-      backgroundColor: Theme.of(context).extension<StackColors>()!.background,
-      appBar: AppBar(
-        backgroundColor: Theme.of(context).extension<StackColors>()!.background,
-        leading: AppBarBackButton(
-          onPressed: () async {
-            // if (FocusScope.of(context).hasFocus) {
-            //   FocusScope.of(context).unfocus();
-            //   await Future<void>.delayed(Duration(milliseconds: 50));
-            // }
-            Navigator.of(context).pop();
-          },
-        ),
-        title: Text(
-          "Confirm transaction",
-          style: STextStyles.navBarTitle(context),
-        ),
-      ),
-      body: LayoutBuilder(
-        builder: (builderContext, constraints) {
-          return Padding(
-            padding: const EdgeInsets.only(
-              left: 12,
-              top: 12,
-              right: 12,
-            ),
-            child: SingleChildScrollView(
-              child: ConstrainedBox(
-                constraints: BoxConstraints(
-                  minHeight: constraints.maxHeight - 24,
-                ),
-                child: IntrinsicHeight(
-                  child: Padding(
-                    padding: const EdgeInsets.all(4),
-                    child: Column(
-                      crossAxisAlignment: CrossAxisAlignment.stretch,
-                      children: [
-                        Text(
-                          "Send ${ref.watch(managerProvider.select((value) => value.coin)).ticker}",
-                          style: STextStyles.pageTitleH1(context),
-                        ),
-                        const SizedBox(
-                          height: 12,
-                        ),
-                        RoundedWhiteContainer(
-                          child: Column(
-                            crossAxisAlignment: CrossAxisAlignment.stretch,
-                            children: [
-                              Text(
-                                "Send from",
-                                style: STextStyles.smallMed12(context),
-                              ),
-                              const SizedBox(
-                                height: 4,
-                              ),
-                              Text(
-                                ref
-                                    .watch(walletsChangeNotifierProvider)
-                                    .getManager(walletId)
-                                    .walletName,
-                                style: STextStyles.itemSubtitle12(context),
-                              ),
-                            ],
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 12,
-                        ),
-                        const SizedBox(
-                          height: 12,
-                        ),
-                        RoundedWhiteContainer(
-                          child: Column(
-                            crossAxisAlignment: CrossAxisAlignment.stretch,
-                            children: [
-                              Text(
-                                "${trade.exchangeName} address",
-                                style: STextStyles.smallMed12(context),
-                              ),
-                              const SizedBox(
-                                height: 4,
-                              ),
-                              Text(
-                                "${transactionInfo["address"] ?? "ERROR"}",
-                                style: STextStyles.itemSubtitle12(context),
-                              ),
-                            ],
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 12,
-                        ),
-                        RoundedWhiteContainer(
-                          child: Row(
-                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                            children: [
-                              Text(
-                                "Amount",
-                                style: STextStyles.smallMed12(context),
-                              ),
-                              Text(
-                                "${Format.satoshiAmountToPrettyString(
-                                  transactionInfo["recipientAmt"] as int,
-                                  ref.watch(
-                                    localeServiceChangeNotifierProvider
-                                        .select((value) => value.locale),
-                                  ),
-                                )} ${ref.watch(
-                                      managerProvider
-                                          .select((value) => value.coin),
-                                    ).ticker}",
-                                style: STextStyles.itemSubtitle12(context),
-                                textAlign: TextAlign.right,
-                              ),
-                            ],
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 12,
-                        ),
-                        RoundedWhiteContainer(
-                          child: Row(
-                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                            children: [
-                              Text(
-                                "Transaction fee",
-                                style: STextStyles.smallMed12(context),
-                              ),
-                              Text(
-                                "${Format.satoshiAmountToPrettyString(
-                                  transactionInfo["fee"] as int,
-                                  ref.watch(
-                                    localeServiceChangeNotifierProvider
-                                        .select((value) => value.locale),
-                                  ),
-                                )} ${ref.watch(
-                                      managerProvider
-                                          .select((value) => value.coin),
-                                    ).ticker}",
-                                style: STextStyles.itemSubtitle12(context),
-                                textAlign: TextAlign.right,
-                              ),
-                            ],
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 12,
-                        ),
-                        RoundedWhiteContainer(
-                          child: Column(
-                            crossAxisAlignment: CrossAxisAlignment.stretch,
-                            children: [
-                              Text(
-                                "Note",
-                                style: STextStyles.smallMed12(context),
-                              ),
-                              const SizedBox(
-                                height: 4,
-                              ),
-                              Text(
-                                transactionInfo["note"] as String? ?? "",
-                                style: STextStyles.itemSubtitle12(context),
-                              ),
-                            ],
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 12,
-                        ),
-                        RoundedWhiteContainer(
-                          child: Row(
-                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                            children: [
-                              Text(
-                                "Trade ID",
-                                style: STextStyles.smallMed12(context),
-                              ),
-                              Text(
-                                trade.tradeId,
-                                style: STextStyles.itemSubtitle12(context),
-                                textAlign: TextAlign.right,
-                              ),
-                            ],
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 12,
-                        ),
-                        RoundedContainer(
-                          color: Theme.of(context)
-                              .extension<StackColors>()!
-                              .snackBarBackSuccess,
-                          child: Row(
-                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                            children: [
-                              Text(
-                                "Total amount",
-                                style:
-                                    STextStyles.titleBold12(context).copyWith(
-                                  color: Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textConfirmTotalAmount,
-                                ),
-                              ),
-                              Text(
-                                "${Format.satoshiAmountToPrettyString(
-                                  (transactionInfo["fee"] as int) +
-                                      (transactionInfo["recipientAmt"] as int),
-                                  ref.watch(
-                                    localeServiceChangeNotifierProvider
-                                        .select((value) => value.locale),
-                                  ),
-                                )} ${ref.watch(
-                                      managerProvider
-                                          .select((value) => value.coin),
-                                    ).ticker}",
-                                style: STextStyles.itemSubtitle12(context)
-                                    .copyWith(
-                                  color: Theme.of(context)
-                                      .extension<StackColors>()!
-                                      .textConfirmTotalAmount,
-                                ),
-                                textAlign: TextAlign.right,
-                              ),
-                            ],
-                          ),
-                        ),
-                        const SizedBox(
-                          height: 16,
-                        ),
-                        const Spacer(),
-                        TextButton(
-                          style: Theme.of(context)
-                              .extension<StackColors>()!
-                              .getPrimaryEnabledButtonColor(context),
-                          onPressed: () async {
-                            final unlocked = await Navigator.push(
-                              context,
-                              RouteGenerator.getRoute(
-                                shouldUseMaterialRoute:
-                                    RouteGenerator.useMaterialPageRoute,
-                                builder: (_) => const LockscreenView(
-                                  showBackButton: true,
-                                  popOnSuccess: true,
-                                  routeOnSuccessArguments: true,
-                                  routeOnSuccess: "",
-                                  biometricsCancelButtonString: "CANCEL",
-                                  biometricsLocalizedReason:
-                                      "Authenticate to send transaction",
-                                  biometricsAuthenticationTitle:
-                                      "Confirm Transaction",
-                                ),
-                                settings: const RouteSettings(
-                                    name: "/confirmsendlockscreen"),
-                              ),
-                            );
 
-                            if (unlocked is bool && unlocked && mounted) {
-                              await _attemptSend(context);
-                            }
-                          },
-                          child: Text(
-                            "Send",
-                            style: STextStyles.button(context),
-                          ),
-                        ),
-                      ],
+    final isDesktop = Util.isDesktop;
+
+    return ConditionalParent(
+      condition: !isDesktop,
+      builder: (child) {
+        return Scaffold(
+          backgroundColor:
+              Theme.of(context).extension<StackColors>()!.background,
+          appBar: AppBar(
+            backgroundColor:
+                Theme.of(context).extension<StackColors>()!.background,
+            leading: AppBarBackButton(
+              onPressed: () async {
+                // if (FocusScope.of(context).hasFocus) {
+                //   FocusScope.of(context).unfocus();
+                //   await Future<void>.delayed(Duration(milliseconds: 50));
+                // }
+                Navigator.of(context).pop();
+              },
+            ),
+            title: Text(
+              "Confirm transaction",
+              style: STextStyles.navBarTitle(context),
+            ),
+          ),
+          body: LayoutBuilder(
+            builder: (builderContext, constraints) {
+              return Padding(
+                padding: const EdgeInsets.only(
+                  left: 12,
+                  top: 12,
+                  right: 12,
+                ),
+                child: SingleChildScrollView(
+                  child: ConstrainedBox(
+                    constraints: BoxConstraints(
+                      minHeight: constraints.maxHeight - 24,
+                    ),
+                    child: IntrinsicHeight(
+                      child: Padding(
+                        padding: const EdgeInsets.all(4),
+                        child: child,
+                      ),
                     ),
                   ),
                 ),
+              );
+            },
+          ),
+        );
+      },
+      child: ConditionalParent(
+        condition: isDesktop,
+        builder: (child) => DesktopDialog(
+          maxHeight: double.infinity,
+          maxWidth: 580,
+          child: Column(
+            children: [
+              Row(
+                children: [
+                  const SizedBox(
+                    width: 6,
+                  ),
+                  const AppBarBackButton(
+                    isCompact: true,
+                    iconSize: 23,
+                  ),
+                  const SizedBox(
+                    width: 12,
+                  ),
+                  Text(
+                    "Confirm ${ref.watch(managerProvider.select((value) => value.coin)).ticker} transaction",
+                    style: STextStyles.desktopH3(context),
+                  )
+                ],
+              ),
+              Padding(
+                padding: const EdgeInsets.only(
+                  left: 32,
+                  right: 32,
+                  bottom: 32,
+                ),
+                child: Column(
+                  children: [
+                    RoundedWhiteContainer(
+                      padding: const EdgeInsets.all(0),
+                      borderColor: Theme.of(context)
+                          .extension<StackColors>()!
+                          .background,
+                      child: child,
+                    ),
+                    const SizedBox(
+                      height: 16,
+                    ),
+                    Row(
+                      children: [
+                        Text(
+                          "Transaction fee",
+                          style:
+                              STextStyles.desktopTextExtraExtraSmall(context),
+                        ),
+                      ],
+                    ),
+                    const SizedBox(
+                      height: 10,
+                    ),
+                    RoundedContainer(
+                      color: Theme.of(context)
+                          .extension<StackColors>()!
+                          .textFieldDefaultBG,
+                      child: Row(
+                        mainAxisAlignment: MainAxisAlignment.end,
+                        children: [
+                          Text(
+                            "${Format.satoshiAmountToPrettyString(
+                              (transactionInfo["fee"] as int),
+                              ref.watch(
+                                localeServiceChangeNotifierProvider
+                                    .select((value) => value.locale),
+                              ),
+                            )} ${ref.watch(
+                                  managerProvider.select((value) => value.coin),
+                                ).ticker}",
+                            style:
+                                STextStyles.desktopTextExtraExtraSmall(context)
+                                    .copyWith(
+                              color: Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textDark,
+                            ),
+                          ),
+                        ],
+                      ),
+                    ),
+                    const SizedBox(
+                      height: 16,
+                    ),
+                    RoundedContainer(
+                      color: Theme.of(context)
+                          .extension<StackColors>()!
+                          .snackBarBackSuccess,
+                      child: Row(
+                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                        children: [
+                          Text(
+                            "Total amount",
+                            style: STextStyles.titleBold12(context).copyWith(
+                              color: Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textConfirmTotalAmount,
+                            ),
+                          ),
+                          Text(
+                            "${Format.satoshiAmountToPrettyString(
+                              (transactionInfo["fee"] as int) +
+                                  (transactionInfo["recipientAmt"] as int),
+                              ref.watch(
+                                localeServiceChangeNotifierProvider
+                                    .select((value) => value.locale),
+                              ),
+                            )} ${ref.watch(
+                                  managerProvider.select((value) => value.coin),
+                                ).ticker}",
+                            style: STextStyles.itemSubtitle12(context).copyWith(
+                              color: Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textConfirmTotalAmount,
+                            ),
+                            textAlign: TextAlign.right,
+                          ),
+                        ],
+                      ),
+                    ),
+                    const SizedBox(
+                      height: 16,
+                    ),
+                    Row(
+                      children: [
+                        Expanded(
+                          child: SecondaryButton(
+                            label: "Cancel",
+                            buttonHeight: ButtonHeight.l,
+                            onPressed: Navigator.of(context).pop,
+                          ),
+                        ),
+                        const SizedBox(
+                          width: 16,
+                        ),
+                        Expanded(
+                          child: PrimaryButton(
+                            label: "Send",
+                            buttonHeight: isDesktop ? ButtonHeight.l : null,
+                            onPressed: _confirmSend,
+                          ),
+                        ),
+                      ],
+                    )
+                  ],
+                ),
+              ),
+            ],
+          ),
+        ),
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.stretch,
+          children: [
+            ConditionalParent(
+              condition: isDesktop,
+              builder: (child) => Container(
+                decoration: BoxDecoration(
+                  color: Theme.of(context).extension<StackColors>()!.background,
+                  borderRadius: BorderRadius.vertical(
+                    top: Radius.circular(
+                      Constants.size.circularBorderRadius,
+                    ),
+                  ),
+                ),
+                child: Padding(
+                  padding: const EdgeInsets.all(12),
+                  child: Row(
+                    children: [
+                      child,
+                    ],
+                  ),
+                ),
+              ),
+              child: Text(
+                "Send ${ref.watch(managerProvider.select((value) => value.coin)).ticker}",
+                style: isDesktop
+                    ? STextStyles.desktopTextMedium(context)
+                    : STextStyles.pageTitleH1(context),
               ),
             ),
-          );
-        },
+            isDesktop
+                ? Container(
+                    color:
+                        Theme.of(context).extension<StackColors>()!.background,
+                    height: 1,
+                  )
+                : const SizedBox(
+                    height: 12,
+                  ),
+            RoundedWhiteContainer(
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.stretch,
+                children: [
+                  Text(
+                    "Send from",
+                    style: STextStyles.smallMed12(context),
+                  ),
+                  const SizedBox(
+                    height: 4,
+                  ),
+                  Text(
+                    ref
+                        .watch(walletsChangeNotifierProvider)
+                        .getManager(walletId)
+                        .walletName,
+                    style: STextStyles.itemSubtitle12(context),
+                  ),
+                ],
+              ),
+            ),
+            isDesktop
+                ? Container(
+                    color:
+                        Theme.of(context).extension<StackColors>()!.background,
+                    height: 1,
+                  )
+                : const SizedBox(
+                    height: 12,
+                  ),
+            RoundedWhiteContainer(
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.stretch,
+                children: [
+                  Text(
+                    "${trade.exchangeName} address",
+                    style: STextStyles.smallMed12(context),
+                  ),
+                  const SizedBox(
+                    height: 4,
+                  ),
+                  Text(
+                    "${transactionInfo["address"] ?? "ERROR"}",
+                    style: STextStyles.itemSubtitle12(context),
+                  ),
+                ],
+              ),
+            ),
+            isDesktop
+                ? Container(
+                    color:
+                        Theme.of(context).extension<StackColors>()!.background,
+                    height: 1,
+                  )
+                : const SizedBox(
+                    height: 12,
+                  ),
+            RoundedWhiteContainer(
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                children: [
+                  Text(
+                    "Amount",
+                    style: STextStyles.smallMed12(context),
+                  ),
+                  ConditionalParent(
+                    condition: isDesktop,
+                    builder: (child) => Row(
+                      children: [
+                        child,
+                        Builder(builder: (context) {
+                          final coin = ref.watch(
+                              walletsChangeNotifierProvider.select(
+                                  (value) => value.getManager(walletId).coin));
+                          final price = ref.watch(
+                              priceAnd24hChangeNotifierProvider
+                                  .select((value) => value.getPrice(coin)));
+                          final amount = Format.satoshisToAmount(
+                            transactionInfo["recipientAmt"] as int,
+                            coin: coin,
+                          );
+                          final value = price.item1 * amount;
+                          final currency = ref.watch(prefsChangeNotifierProvider
+                              .select((value) => value.currency));
+
+                          return Text(
+                            " | ${value.toStringAsFixed(Constants.decimalPlacesForCoin(coin))} $currency",
+                            style:
+                                STextStyles.desktopTextExtraExtraSmall(context)
+                                    .copyWith(
+                              color: Theme.of(context)
+                                  .extension<StackColors>()!
+                                  .textSubtitle2,
+                            ),
+                          );
+                        })
+                      ],
+                    ),
+                    child: Text(
+                      "${Format.satoshiAmountToPrettyString(
+                        transactionInfo["recipientAmt"] as int,
+                        ref.watch(
+                          localeServiceChangeNotifierProvider
+                              .select((value) => value.locale),
+                        ),
+                      )} ${ref.watch(
+                            managerProvider.select((value) => value.coin),
+                          ).ticker}",
+                      style: STextStyles.itemSubtitle12(context),
+                      textAlign: TextAlign.right,
+                    ),
+                  ),
+                ],
+              ),
+            ),
+            isDesktop
+                ? Container(
+                    color:
+                        Theme.of(context).extension<StackColors>()!.background,
+                    height: 1,
+                  )
+                : const SizedBox(
+                    height: 12,
+                  ),
+            RoundedWhiteContainer(
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                children: [
+                  Text(
+                    "Transaction fee",
+                    style: STextStyles.smallMed12(context),
+                  ),
+                  Text(
+                    "${Format.satoshiAmountToPrettyString(
+                      transactionInfo["fee"] as int,
+                      ref.watch(
+                        localeServiceChangeNotifierProvider
+                            .select((value) => value.locale),
+                      ),
+                    )} ${ref.watch(
+                          managerProvider.select((value) => value.coin),
+                        ).ticker}",
+                    style: STextStyles.itemSubtitle12(context),
+                    textAlign: TextAlign.right,
+                  ),
+                ],
+              ),
+            ),
+            isDesktop
+                ? Container(
+                    color:
+                        Theme.of(context).extension<StackColors>()!.background,
+                    height: 1,
+                  )
+                : const SizedBox(
+                    height: 12,
+                  ),
+            RoundedWhiteContainer(
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.stretch,
+                children: [
+                  Text(
+                    "Note",
+                    style: STextStyles.smallMed12(context),
+                  ),
+                  const SizedBox(
+                    height: 4,
+                  ),
+                  Text(
+                    transactionInfo["note"] as String? ?? "",
+                    style: STextStyles.itemSubtitle12(context),
+                  ),
+                ],
+              ),
+            ),
+            isDesktop
+                ? Container(
+                    color:
+                        Theme.of(context).extension<StackColors>()!.background,
+                    height: 1,
+                  )
+                : const SizedBox(
+                    height: 12,
+                  ),
+            RoundedWhiteContainer(
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                children: [
+                  Text(
+                    "Trade ID",
+                    style: STextStyles.smallMed12(context),
+                  ),
+                  Text(
+                    trade.tradeId,
+                    style: STextStyles.itemSubtitle12(context),
+                    textAlign: TextAlign.right,
+                  ),
+                ],
+              ),
+            ),
+            if (!isDesktop)
+              const SizedBox(
+                height: 12,
+              ),
+            if (!isDesktop)
+              RoundedContainer(
+                color: Theme.of(context)
+                    .extension<StackColors>()!
+                    .snackBarBackSuccess,
+                child: Row(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  children: [
+                    Text(
+                      "Total amount",
+                      style: STextStyles.titleBold12(context).copyWith(
+                        color: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textConfirmTotalAmount,
+                      ),
+                    ),
+                    Text(
+                      "${Format.satoshiAmountToPrettyString(
+                        (transactionInfo["fee"] as int) +
+                            (transactionInfo["recipientAmt"] as int),
+                        ref.watch(
+                          localeServiceChangeNotifierProvider
+                              .select((value) => value.locale),
+                        ),
+                      )} ${ref.watch(
+                            managerProvider.select((value) => value.coin),
+                          ).ticker}",
+                      style: STextStyles.itemSubtitle12(context).copyWith(
+                        color: Theme.of(context)
+                            .extension<StackColors>()!
+                            .textConfirmTotalAmount,
+                      ),
+                      textAlign: TextAlign.right,
+                    ),
+                  ],
+                ),
+              ),
+            if (!isDesktop)
+              const SizedBox(
+                height: 16,
+              ),
+            if (!isDesktop) const Spacer(),
+            if (!isDesktop)
+              PrimaryButton(
+                label: "Send",
+                buttonHeight: isDesktop ? ButtonHeight.l : null,
+                onPressed: _confirmSend,
+              ),
+          ],
+        ),
       ),
     );
   }
diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart
index 59675e4e4..7cbf38384 100644
--- a/lib/pages/exchange_view/send_from_view.dart
+++ b/lib/pages/exchange_view/send_from_view.dart
@@ -7,8 +7,8 @@ import 'package:flutter_svg/svg.dart';
 import 'package:stackwallet/models/exchange/response_objects/trade.dart';
 import 'package:stackwallet/pages/exchange_view/confirm_change_now_send.dart';
 import 'package:stackwallet/pages/home_view/home_view.dart';
-import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
 import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dialog.dart';
+import 'package:stackwallet/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart';
 import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/route_generator.dart';
 import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
@@ -30,8 +30,6 @@ import 'package:stackwallet/widgets/expandable.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_dialog.dart';
 
-import '../../pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart';
-
 class SendFromView extends ConsumerStatefulWidget {
   const SendFromView({
     Key? key,
@@ -39,6 +37,7 @@ class SendFromView extends ConsumerStatefulWidget {
     required this.trade,
     required this.amount,
     required this.address,
+    this.shouldPopRoot = false,
   }) : super(key: key);
 
   static const String routeName = "/sendFrom";
@@ -47,6 +46,7 @@ class SendFromView extends ConsumerStatefulWidget {
   final Decimal amount;
   final String address;
   final Trade trade;
+  final bool shouldPopRoot;
 
   @override
   ConsumerState<SendFromView> createState() => _SendFromViewState();
@@ -142,7 +142,7 @@ class _SendFromViewState extends ConsumerState<SendFromView> {
                   DesktopDialogCloseButton(
                     onPressedOverride: Navigator.of(
                       context,
-                      rootNavigator: false,
+                      rootNavigator: widget.shouldPopRoot,
                     ).pop,
                   ),
                 ],
@@ -239,12 +239,23 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
           useSafeArea: false,
           barrierDismissible: false,
           builder: (context) {
-            return BuildingTransactionDialog(
-              onCancel: () {
-                wasCancelled = true;
+            return ConditionalParent(
+              condition: Util.isDesktop,
+              builder: (child) => DesktopDialog(
+                maxWidth: 400,
+                maxHeight: double.infinity,
+                child: Padding(
+                  padding: const EdgeInsets.all(32),
+                  child: child,
+                ),
+              ),
+              child: BuildingTransactionDialog(
+                onCancel: () {
+                  wasCancelled = true;
 
-                Navigator.of(context).pop();
-              },
+                  Navigator.of(context).pop();
+                },
+              ),
             );
           },
         ),
@@ -290,7 +301,10 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
         // pop building dialog
 
         if (mounted) {
-          Navigator.of(context).pop();
+          Navigator.of(
+            context,
+            rootNavigator: Util.isDesktop,
+          ).pop();
         }
 
         txData["note"] =
@@ -304,7 +318,9 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
               builder: (_) => ConfirmChangeNowSendView(
                 transactionInfo: txData,
                 walletId: walletId,
-                routeOnSuccessName: HomeView.routeName,
+                routeOnSuccessName: Util.isDesktop
+                    ? DesktopExchangeView.routeName
+                    : HomeView.routeName,
                 trade: trade,
                 shouldSendPublicFiroFunds: shouldSendPublicFiroFunds,
               ),
@@ -401,58 +417,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
                   ),
                 ),
                 onPressed: () async {
-                  final dynamic unlocked;
-
-                  if (Util.isDesktop) {
-                    unlocked = await showDialog<bool?>(
-                      context: context,
-                      builder: (context) => DesktopDialog(
-                        maxWidth: 580,
-                        maxHeight: double.infinity,
-                        child: Column(
-                          mainAxisSize: MainAxisSize.min,
-                          children: [
-                            Row(
-                              mainAxisAlignment: MainAxisAlignment.end,
-                              children: const [
-                                DesktopDialogCloseButton(),
-                              ],
-                            ),
-                            const Padding(
-                              padding: EdgeInsets.only(
-                                left: 32,
-                                right: 32,
-                                bottom: 32,
-                              ),
-                              child: DesktopAuthSend(),
-                            ),
-                          ],
-                        ),
-                      ),
-                    );
-                  } else {
-                    unlocked = await Navigator.push(
-                      context,
-                      RouteGenerator.getRoute(
-                        shouldUseMaterialRoute:
-                            RouteGenerator.useMaterialPageRoute,
-                        builder: (_) => const LockscreenView(
-                          showBackButton: true,
-                          popOnSuccess: true,
-                          routeOnSuccessArguments: true,
-                          routeOnSuccess: "",
-                          biometricsCancelButtonString: "CANCEL",
-                          biometricsLocalizedReason:
-                              "Authenticate to send transaction",
-                          biometricsAuthenticationTitle: "Confirm Transaction",
-                        ),
-                        settings:
-                            const RouteSettings(name: "/confirmsendlockscreen"),
-                      ),
-                    );
-                  }
-
-                  if (unlocked is bool && unlocked && mounted) {
+                  if (mounted) {
                     unawaited(
                       _send(
                         manager,
@@ -537,58 +502,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
                   ),
                 ),
                 onPressed: () async {
-                  final dynamic unlocked;
-
-                  if (Util.isDesktop) {
-                    unlocked = await showDialog<bool?>(
-                      context: context,
-                      builder: (context) => DesktopDialog(
-                        maxWidth: 580,
-                        maxHeight: double.infinity,
-                        child: Column(
-                          mainAxisSize: MainAxisSize.min,
-                          children: [
-                            Row(
-                              mainAxisAlignment: MainAxisAlignment.end,
-                              children: const [
-                                DesktopDialogCloseButton(),
-                              ],
-                            ),
-                            const Padding(
-                              padding: EdgeInsets.only(
-                                left: 32,
-                                right: 32,
-                                bottom: 32,
-                              ),
-                              child: DesktopAuthSend(),
-                            ),
-                          ],
-                        ),
-                      ),
-                    );
-                  } else {
-                    unlocked = await Navigator.push(
-                      context,
-                      RouteGenerator.getRoute(
-                        shouldUseMaterialRoute:
-                            RouteGenerator.useMaterialPageRoute,
-                        builder: (_) => const LockscreenView(
-                          showBackButton: true,
-                          popOnSuccess: true,
-                          routeOnSuccessArguments: true,
-                          routeOnSuccess: "",
-                          biometricsCancelButtonString: "CANCEL",
-                          biometricsLocalizedReason:
-                              "Authenticate to send transaction",
-                          biometricsAuthenticationTitle: "Confirm Transaction",
-                        ),
-                        settings:
-                            const RouteSettings(name: "/confirmsendlockscreen"),
-                      ),
-                    );
-                  }
-
-                  if (unlocked is bool && unlocked && mounted) {
+                  if (mounted) {
                     unawaited(
                       _send(
                         manager,
@@ -680,57 +594,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
               ),
             ),
             onPressed: () async {
-              final dynamic unlocked;
-
-              if (Util.isDesktop) {
-                unlocked = await showDialog<bool?>(
-                  context: context,
-                  builder: (context) => DesktopDialog(
-                    maxWidth: 580,
-                    maxHeight: double.infinity,
-                    child: Column(
-                      mainAxisSize: MainAxisSize.min,
-                      children: [
-                        Row(
-                          mainAxisAlignment: MainAxisAlignment.end,
-                          children: const [
-                            DesktopDialogCloseButton(),
-                          ],
-                        ),
-                        const Padding(
-                          padding: EdgeInsets.only(
-                            left: 32,
-                            right: 32,
-                            bottom: 32,
-                          ),
-                          child: DesktopAuthSend(),
-                        ),
-                      ],
-                    ),
-                  ),
-                );
-              } else {
-                unlocked = await Navigator.push(
-                  context,
-                  RouteGenerator.getRoute(
-                    shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute,
-                    builder: (_) => const LockscreenView(
-                      showBackButton: true,
-                      popOnSuccess: true,
-                      routeOnSuccessArguments: true,
-                      routeOnSuccess: "",
-                      biometricsCancelButtonString: "CANCEL",
-                      biometricsLocalizedReason:
-                          "Authenticate to send transaction",
-                      biometricsAuthenticationTitle: "Confirm Transaction",
-                    ),
-                    settings:
-                        const RouteSettings(name: "/confirmsendlockscreen"),
-                  ),
-                );
-              }
-
-              if (unlocked is bool && unlocked && mounted) {
+              if (mounted) {
                 unawaited(
                   _send(manager),
                 );
diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart
index f28d1d617..0b7f4b502 100644
--- a/lib/pages/exchange_view/trade_details_view.dart
+++ b/lib/pages/exchange_view/trade_details_view.dart
@@ -219,7 +219,8 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
                       children: children,
                     ),
                   ),
-                  if (isStackCoin(trade.payInCurrency) &&
+                  if (!hasTx &&
+                      isStackCoin(trade.payInCurrency) &&
                       (trade.status == "New" ||
                           trade.status == "new" ||
                           trade.status == "waiting" ||
@@ -227,7 +228,8 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
                     const SizedBox(
                       height: 32,
                     ),
-                  if (isStackCoin(trade.payInCurrency) &&
+                  if (!hasTx &&
+                      isStackCoin(trade.payInCurrency) &&
                       (trade.status == "New" ||
                           trade.status == "new" ||
                           trade.status == "waiting" ||
@@ -1142,6 +1144,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
                 height: 12,
               ),
             if (!isDesktop &&
+                !hasTx &&
                 isStackCoin(trade.payInCurrency) &&
                 (trade.status == "New" ||
                     trade.status == "new" ||
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
index 525d561fc..7b793210c 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_2.dart
@@ -51,6 +51,8 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
   late final FocusNode _toFocusNode;
   late final FocusNode _refundFocusNode;
 
+  bool enableNext = false;
+
   bool isStackCoin(String ticker) {
     try {
       coinFromTickerCaseInsensitive(ticker);
@@ -60,13 +62,13 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
     }
   }
 
-  void selectRecipientAddressFromStack() {
+  void selectRecipientAddressFromStack() async {
     try {
       final coin = coinFromTickerCaseInsensitive(
         model.receiveTicker,
       );
 
-      showDialog<String?>(
+      final address = await showDialog<String?>(
         context: context,
         barrierColor: Colors.transparent,
         builder: (context) => DesktopDialog(
@@ -79,27 +81,31 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
             ),
           ),
         ),
-      ).then((value) async {
-        if (value is String) {
-          final manager =
-              ref.read(walletsChangeNotifierProvider).getManager(value);
+      );
 
-          _toController.text = manager.walletName;
-          model.recipientAddress = await manager.currentReceivingAddress;
-        }
-      });
+      if (address is String) {
+        final manager =
+            ref.read(walletsChangeNotifierProvider).getManager(address);
+
+        _toController.text = manager.walletName;
+        model.recipientAddress = await manager.currentReceivingAddress;
+      }
     } catch (e, s) {
       Logging.instance.log("$e\n$s", level: LogLevel.Info);
     }
+    setState(() {
+      enableNext =
+          _toController.text.isNotEmpty && _refundController.text.isNotEmpty;
+    });
   }
 
-  void selectRefundAddressFromStack() {
+  void selectRefundAddressFromStack() async {
     try {
       final coin = coinFromTickerCaseInsensitive(
         model.sendTicker,
       );
 
-      showDialog<String?>(
+      final address = await showDialog<String?>(
         context: context,
         barrierColor: Colors.transparent,
         builder: (context) => DesktopDialog(
@@ -112,18 +118,21 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
             ),
           ),
         ),
-      ).then((value) async {
-        if (value is String) {
-          final manager =
-              ref.read(walletsChangeNotifierProvider).getManager(value);
+      );
+      if (address is String) {
+        final manager =
+            ref.read(walletsChangeNotifierProvider).getManager(address);
 
-          _refundController.text = manager.walletName;
-          model.refundAddress = await manager.currentReceivingAddress;
-        }
-      });
+        _refundController.text = manager.walletName;
+        model.refundAddress = await manager.currentReceivingAddress;
+      }
     } catch (e, s) {
       Logging.instance.log("$e\n$s", level: LogLevel.Info);
     }
+    setState(() {
+      enableNext =
+          _toController.text.isNotEmpty && _refundController.text.isNotEmpty;
+    });
   }
 
   void selectRecipientFromAddressBook() async {
@@ -168,7 +177,10 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
     if (entry != null) {
       _toController.text = entry.address;
       model.recipientAddress = entry.address;
-      setState(() {});
+      setState(() {
+        enableNext =
+            _toController.text.isNotEmpty && _refundController.text.isNotEmpty;
+      });
     }
   }
 
@@ -214,7 +226,10 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
     if (entry != null) {
       _refundController.text = entry.address;
       model.refundAddress = entry.address;
-      setState(() {});
+      setState(() {
+        enableNext =
+            _toController.text.isNotEmpty && _refundController.text.isNotEmpty;
+      });
     }
   }
 
@@ -334,7 +349,10 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
             focusNode: _toFocusNode,
             style: STextStyles.field(context),
             onChanged: (value) {
-              setState(() {});
+              setState(() {
+                enableNext = _toController.text.isNotEmpty &&
+                    _refundController.text.isNotEmpty;
+              });
             },
             decoration: standardInputDecoration(
               "Enter the ${model.receiveTicker.toUpperCase()} payout address",
@@ -363,7 +381,10 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
                               onTap: () {
                                 _toController.text = "";
                                 model.recipientAddress = _toController.text;
-                                setState(() {});
+                                setState(() {
+                                  enableNext = _toController.text.isNotEmpty &&
+                                      _refundController.text.isNotEmpty;
+                                });
                               },
                               child: const XIcon(),
                             )
@@ -378,7 +399,11 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
                                   final content = data.text!.trim();
                                   _toController.text = content;
                                   model.recipientAddress = _toController.text;
-                                  setState(() {});
+                                  setState(() {
+                                    enableNext =
+                                        _toController.text.isNotEmpty &&
+                                            _refundController.text.isNotEmpty;
+                                  });
                                 }
                               },
                               child: _toController.text.isEmpty
@@ -454,7 +479,10 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
             focusNode: _refundFocusNode,
             style: STextStyles.field(context),
             onChanged: (value) {
-              setState(() {});
+              setState(() {
+                enableNext = _toController.text.isNotEmpty &&
+                    _refundController.text.isNotEmpty;
+              });
             },
             decoration: standardInputDecoration(
               "Enter ${model.sendTicker.toUpperCase()} refund address",
@@ -484,7 +512,10 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
                                 _refundController.text = "";
                                 model.refundAddress = _refundController.text;
 
-                                setState(() {});
+                                setState(() {
+                                  enableNext = _toController.text.isNotEmpty &&
+                                      _refundController.text.isNotEmpty;
+                                });
                               },
                               child: const XIcon(),
                             )
@@ -501,7 +532,11 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
                                   _refundController.text = content;
                                   model.refundAddress = _refundController.text;
 
-                                  setState(() {});
+                                  setState(() {
+                                    enableNext =
+                                        _toController.text.isNotEmpty &&
+                                            _refundController.text.isNotEmpty;
+                                  });
                                 }
                               },
                               child: _refundController.text.isEmpty
@@ -552,6 +587,7 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
               Expanded(
                 child: PrimaryButton(
                   label: "Next",
+                  enabled: enableNext,
                   buttonHeight: ButtonHeight.l,
                   onPressed: () async {
                     await showDialog<void>(
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
index 7747f570f..c86713a76 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
@@ -1,11 +1,14 @@
 import 'dart:async';
 
+import 'package:decimal/decimal.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:qr_flutter/qr_flutter.dart';
 import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
+import 'package:stackwallet/pages/exchange_view/send_from_view.dart';
 import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
 import 'package:stackwallet/providers/providers.dart';
+import 'package:stackwallet/route_generator.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
@@ -199,7 +202,38 @@ class _DesktopStep4State extends ConsumerState<DesktopStep4> {
                 child: SecondaryButton(
                   label: "Send from Stack Wallet",
                   buttonHeight: ButtonHeight.l,
-                  onPressed: Navigator.of(context).pop,
+                  onPressed: () {
+                    final trade = model.trade!;
+                    final amount = Decimal.parse(trade.payInAmount);
+                    final address = trade.payInAddress;
+
+                    final coin =
+                        coinFromTickerCaseInsensitive(trade.payInCurrency);
+
+                    showDialog<void>(
+                      context: context,
+                      builder: (context) => Navigator(
+                        initialRoute: SendFromView.routeName,
+                        onGenerateRoute: RouteGenerator.generateRoute,
+                        onGenerateInitialRoutes: (_, __) {
+                          return [
+                            FadePageRoute(
+                              SendFromView(
+                                coin: coin,
+                                trade: trade,
+                                amount: amount,
+                                address: address,
+                                shouldPopRoot: true,
+                              ),
+                              const RouteSettings(
+                                name: SendFromView.routeName,
+                              ),
+                            ),
+                          ];
+                        },
+                      ),
+                    );
+                  },
                 ),
               ),
               const SizedBox(

From c5c0443d000d425b86056d27dda575a3b895fde6 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Tue, 22 Nov 2022 08:57:05 -0700
Subject: [PATCH 089/100] button sizing fix

---
 .../home/settings_menu/currency_settings/currency_settings.dart | 2 +-
 .../home/settings_menu/language_settings/language_settings.dart | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart b/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart
index d9c20d8fa..9f5f42b7c 100644
--- a/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart
@@ -107,7 +107,7 @@ class _CurrencySettings extends ConsumerState<CurrencySettings> {
                         10,
                       ),
                       child: PrimaryButton(
-                        width: 210,
+                        width: 200,
                         buttonHeight: ButtonHeight.m,
                         enabled: true,
                         label: "Change currency",
diff --git a/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart b/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart
index acddcb055..3c511236c 100644
--- a/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart
+++ b/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart
@@ -84,7 +84,7 @@ class _LanguageOptionSettings extends ConsumerState<LanguageOptionSettings> {
                         10,
                       ),
                       child: PrimaryButton(
-                        width: 210,
+                        width: 200,
                         buttonHeight: ButtonHeight.m,
                         enabled: true,
                         label: "Change language",

From 9a47ce349e52a12d2be80ab7f48ede2b9ca7f379 Mon Sep 17 00:00:00 2001
From: ryleedavis <rylee@cypherstack.com>
Date: Tue, 22 Nov 2022 11:48:47 -0700
Subject: [PATCH 090/100] submit on enter passphrase

---
 .../desktop_attention_delete_wallet.dart      |   3 +-
 .../desktop_delete_wallet_dialog.dart         | 126 +++++++++---------
 2 files changed, 66 insertions(+), 63 deletions(-)

diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart
index 6eb04502e..a614be3a6 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart
@@ -1,5 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/delete_wallet_keys_popup.dart';
 import 'package:stackwallet/providers/global/wallets_provider.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
@@ -10,8 +11,6 @@ import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/rounded_container.dart';
 import 'package:tuple/tuple.dart';
 
-import 'delete_wallet_keys_popup.dart';
-
 class DesktopAttentionDeleteWallet extends ConsumerStatefulWidget {
   const DesktopAttentionDeleteWallet({
     Key? key,
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
index 6729d33b9..e8d9c2dc5 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart
@@ -5,6 +5,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/svg.dart';
 import 'package:stackwallet/notifications/show_flush_bar.dart';
 import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_attention_delete_wallet.dart';
+import 'package:stackwallet/providers/desktop/storage_crypto_handler_provider.dart';
+import 'package:stackwallet/providers/global/wallets_provider.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
@@ -16,9 +18,6 @@ import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/stack_text_field.dart';
 
-import '../../../../../providers/desktop/storage_crypto_handler_provider.dart';
-import '../../../../../providers/global/wallets_provider.dart';
-
 class DesktopDeleteWalletDialog extends ConsumerStatefulWidget {
   const DesktopDeleteWalletDialog({
     Key? key,
@@ -42,6 +41,62 @@ class _DesktopDeleteWalletDialog
   bool hidePassword = true;
   bool _continueEnabled = false;
 
+  Future<void> enterPassphrase() async {
+    unawaited(
+      showDialog(
+        context: context,
+        builder: (context) => Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: const [
+            LoadingIndicator(
+              width: 200,
+              height: 200,
+            ),
+          ],
+        ),
+      ),
+    );
+
+    await Future<void>.delayed(const Duration(seconds: 1));
+
+    final verified = await ref
+        .read(storageCryptoHandlerProvider)
+        .verifyPassphrase(passwordController.text);
+
+    if (verified) {
+      Navigator.of(context, rootNavigator: true).pop();
+
+      final words = await ref
+          .read(walletsChangeNotifierProvider)
+          .getManager(widget.walletId)
+          .mnemonic;
+
+      if (mounted) {
+        Navigator.of(context).pop();
+
+        unawaited(
+          Navigator.of(context).pushNamed(
+            DesktopAttentionDeleteWallet.routeName,
+            arguments: widget.walletId,
+          ),
+        );
+      }
+    } else {
+      Navigator.of(context, rootNavigator: true).pop();
+
+      await Future<void>.delayed(const Duration(milliseconds: 300));
+
+      unawaited(
+        showFloatingFlushBar(
+          type: FlushBarType.warning,
+          message: "Invalid passphrase!",
+          context: context,
+        ),
+      );
+    }
+  }
+
   @override
   void initState() {
     passwordController = TextEditingController();
@@ -106,6 +161,12 @@ class _DesktopDeleteWalletDialog
                     obscureText: hidePassword,
                     enableSuggestions: false,
                     autocorrect: false,
+                    autofocus: true,
+                    onSubmitted: (_) {
+                      if (_continueEnabled) {
+                        enterPassphrase();
+                      }
+                    },
                     decoration: standardInputDecoration(
                       "Enter password",
                       passwordFocusNode,
@@ -179,64 +240,7 @@ class _DesktopDeleteWalletDialog
                       onPressed: _continueEnabled
                           ? () async {
                               // add loading indicator
-                              unawaited(
-                                showDialog(
-                                  context: context,
-                                  builder: (context) => Column(
-                                    mainAxisAlignment: MainAxisAlignment.center,
-                                    crossAxisAlignment:
-                                        CrossAxisAlignment.center,
-                                    children: const [
-                                      LoadingIndicator(
-                                        width: 200,
-                                        height: 200,
-                                      ),
-                                    ],
-                                  ),
-                                ),
-                              );
-
-                              await Future<void>.delayed(
-                                  const Duration(seconds: 1));
-
-                              final verified = await ref
-                                  .read(storageCryptoHandlerProvider)
-                                  .verifyPassphrase(passwordController.text);
-
-                              if (verified) {
-                                Navigator.of(context, rootNavigator: true)
-                                    .pop();
-
-                                final words = await ref
-                                    .read(walletsChangeNotifierProvider)
-                                    .getManager(widget.walletId)
-                                    .mnemonic;
-
-                                if (mounted) {
-                                  Navigator.of(context).pop();
-
-                                  unawaited(
-                                    Navigator.of(context).pushNamed(
-                                      DesktopAttentionDeleteWallet.routeName,
-                                      arguments: widget.walletId,
-                                    ),
-                                  );
-                                }
-                              } else {
-                                Navigator.of(context, rootNavigator: true)
-                                    .pop();
-
-                                await Future<void>.delayed(
-                                    const Duration(milliseconds: 300));
-
-                                unawaited(
-                                  showFloatingFlushBar(
-                                    type: FlushBarType.warning,
-                                    message: "Invalid passphrase!",
-                                    context: context,
-                                  ),
-                                );
-                              }
+                              enterPassphrase();
                             }
                           : null,
                     ),

From 8e2ff3883d3516ee561d9acb36a89a5de94a0400 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 14:42:24 -0600
Subject: [PATCH 091/100] exchange amount field re style

---
 lib/pages/exchange_view/exchange_form.dart    | 362 ++---------------
 .../textfields/exchange_textfield.dart        | 384 ++++++++++++++++++
 2 files changed, 424 insertions(+), 322 deletions(-)
 create mode 100644 lib/widgets/textfields/exchange_textfield.dart

diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart
index 7f0d9b5d2..921b35bf0 100644
--- a/lib/pages/exchange_view/exchange_form.dart
+++ b/lib/pages/exchange_view/exchange_form.dart
@@ -2,7 +2,6 @@ import 'dart:async';
 
 import 'package:decimal/decimal.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 import 'package:flutter_svg/svg.dart';
@@ -25,6 +24,7 @@ import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
 import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart';
 import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/enums/coin_enum.dart';
 import 'package:stackwallet/utilities/logger.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
@@ -37,10 +37,10 @@ import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
 import 'package:stackwallet/widgets/desktop/primary_button.dart';
 import 'package:stackwallet/widgets/desktop/secondary_button.dart';
 import 'package:stackwallet/widgets/desktop/simple_desktop_dialog.dart';
-import 'package:stackwallet/widgets/loading_indicator.dart';
 import 'package:stackwallet/widgets/rounded_container.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
 import 'package:stackwallet/widgets/stack_dialog.dart';
+import 'package:stackwallet/widgets/textfields/exchange_textfield.dart';
 import 'package:tuple/tuple.dart';
 
 class ExchangeForm extends ConsumerStatefulWidget {
@@ -1226,146 +1226,33 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
         SizedBox(
           height: isDesktop ? 10 : 4,
         ),
-        TextFormField(
-          style: STextStyles.smallMed14(context).copyWith(
+        ExchangeTextField(
+          controller: _sendController,
+          focusNode: _sendFocusNode,
+          textStyle: STextStyles.smallMed14(context).copyWith(
             color: Theme.of(context).extension<StackColors>()!.textDark,
           ),
-          focusNode: _sendFocusNode,
-          controller: _sendController,
-          textAlign: TextAlign.right,
-          enableSuggestions: false,
-          autocorrect: false,
+          buttonColor:
+              Theme.of(context).extension<StackColors>()!.buttonBackSecondary,
+          borderRadius: Constants.size.circularBorderRadius,
+          background:
+              Theme.of(context).extension<StackColors>()!.textFieldDefaultBG,
           onTap: () {
             if (_sendController.text == "-") {
               _sendController.text = "";
             }
           },
           onChanged: sendFieldOnChanged,
-          keyboardType: const TextInputType.numberWithOptions(
-            signed: false,
-            decimal: true,
-          ),
-          inputFormatters: [
-            // regex to validate a crypto amount with 8 decimal places
-            TextInputFormatter.withFunction((oldValue, newValue) =>
-                RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
-                        .hasMatch(newValue.text)
-                    ? newValue
-                    : oldValue),
-          ],
-          decoration: InputDecoration(
-            contentPadding: const EdgeInsets.only(
-              top: 12,
-              right: 12,
-            ),
-            hintText: "0",
-            hintStyle: STextStyles.fieldLabel(context).copyWith(
-              fontSize: 14,
-            ),
-            prefixIcon: FittedBox(
-              fit: BoxFit.scaleDown,
-              alignment: Alignment.centerLeft,
-              child: GestureDetector(
-                onTap: selectSendCurrency,
-                child: Container(
-                  color: Colors.transparent,
-                  child: Padding(
-                    padding: const EdgeInsets.all(12),
-                    child: Row(
-                      children: [
-                        Container(
-                          width: 18,
-                          height: 18,
-                          decoration: BoxDecoration(
-                            borderRadius: BorderRadius.circular(18),
-                          ),
-                          child: Builder(
-                            builder: (context) {
-                              final image = _fetchIconUrlFromTicker(ref.watch(
-                                  exchangeFormStateProvider
-                                      .select((value) => value.fromTicker)));
-
-                              if (image != null && image.isNotEmpty) {
-                                return Center(
-                                  child: SvgPicture.network(
-                                    image,
-                                    height: 18,
-                                    placeholderBuilder: (_) => Container(
-                                      width: 18,
-                                      height: 18,
-                                      decoration: BoxDecoration(
-                                        color: Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .textFieldDefaultBG,
-                                        borderRadius: BorderRadius.circular(
-                                          18,
-                                        ),
-                                      ),
-                                      child: ClipRRect(
-                                        borderRadius: BorderRadius.circular(
-                                          18,
-                                        ),
-                                        child: const LoadingIndicator(),
-                                      ),
-                                    ),
-                                  ),
-                                );
-                              } else {
-                                return Container(
-                                  width: 18,
-                                  height: 18,
-                                  decoration: BoxDecoration(
-                                    // color: Theme.of(context).extension<StackColors>()!.accentColorDark
-                                    borderRadius: BorderRadius.circular(18),
-                                  ),
-                                  child: SvgPicture.asset(
-                                    Assets.svg.circleQuestion,
-                                    width: 18,
-                                    height: 18,
-                                    color: Theme.of(context)
-                                        .extension<StackColors>()!
-                                        .textFieldDefaultBG,
-                                  ),
-                                );
-                              }
-                            },
-                          ),
-                        ),
-                        const SizedBox(
-                          width: 6,
-                        ),
-                        Text(
-                          ref.watch(exchangeFormStateProvider.select((value) =>
-                                  value.fromTicker?.toUpperCase())) ??
-                              "-",
-                          style: STextStyles.smallMed14(context).copyWith(
-                            color: Theme.of(context)
-                                .extension<StackColors>()!
-                                .textDark,
-                          ),
-                        ),
-                        if (!isWalletCoin(coin, true))
-                          const SizedBox(
-                            width: 6,
-                          ),
-                        if (!isWalletCoin(coin, true))
-                          SvgPicture.asset(
-                            Assets.svg.chevronDown,
-                            width: 5,
-                            height: 2.5,
-                            color: Theme.of(context)
-                                .extension<StackColors>()!
-                                .textDark,
-                          ),
-                      ],
-                    ),
-                  ),
-                ),
-              ),
-            ),
-          ),
+          onButtonTap: selectSendCurrency,
+          isWalletCoin: isWalletCoin(coin, true),
+          image: _fetchIconUrlFromTicker(ref.watch(
+              exchangeFormStateProvider.select((value) => value.fromTicker))),
+          ticker: ref.watch(
+              exchangeFormStateProvider.select((value) => value.fromTicker)),
+        ),
+        SizedBox(
+          height: isDesktop ? 10 : 4,
         ),
-
         SizedBox(
           height: isDesktop ? 10 : 4,
         ),
@@ -1422,79 +1309,20 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
             ),
           ],
         ),
-        // Stack(
-        //   children: [
-        //     Positioned.fill(
-        //       child: Align(
-        //         alignment: Alignment.bottomLeft,
-        //         child: Text(
-        //           "You will receive",
-        //           style: STextStyles.itemSubtitle(context).copyWith(
-        //             color:
-        //                 Theme.of(context).extension<StackColors>()!.textDark3,
-        //           ),
-        //         ),
-        //       ),
-        //     ),
-        //     Center(
-        //       child: Column(
-        //         children: [
-        //           const SizedBox(
-        //             height: 6,
-        //           ),
-        //           GestureDetector(
-        //             onTap: () async {
-        //               await _swap();
-        //             },
-        //             child: Padding(
-        //               padding: const EdgeInsets.all(4),
-        //               child: SvgPicture.asset(
-        //                 Assets.svg.swap,
-        //                 width: 20,
-        //                 height: 20,
-        //                 color: Theme.of(context)
-        //                     .extension<StackColors>()!
-        //                     .accentColorDark,
-        //               ),
-        //             ),
-        //           ),
-        //           const SizedBox(
-        //             height: 6,
-        //           ),
-        //         ],
-        //       ),
-        //     ),
-        //     Positioned.fill(
-        //       child: Align(
-        //         alignment: ref.watch(exchangeFormStateProvider
-        //                 .select((value) => value.reversed))
-        //             ? Alignment.bottomRight
-        //             : Alignment.topRight,
-        //         child: Text(
-        //           ref.watch(exchangeFormStateProvider
-        //               .select((value) => value.warning)),
-        //           style: STextStyles.errorSmall(context),
-        //         ),
-        //       ),
-        //     ),
-        //   ],
-        // ),
         SizedBox(
           height: isDesktop ? 10 : 4,
         ),
-        TextFormField(
-          style: STextStyles.smallMed14(context).copyWith(
-            color: Theme.of(context).extension<StackColors>()!.textDark,
-          ),
+        ExchangeTextField(
           focusNode: _receiveFocusNode,
           controller: _receiveController,
-          enableSuggestions: false,
-          autocorrect: false,
-          readOnly: ref.watch(prefsChangeNotifierProvider
-                      .select((value) => value.exchangeRateType)) ==
-                  ExchangeRateType.estimated ||
-              ref.watch(exchangeProvider).name ==
-                  SimpleSwapExchange.exchangeName,
+          textStyle: STextStyles.smallMed14(context).copyWith(
+            color: Theme.of(context).extension<StackColors>()!.textDark,
+          ),
+          buttonColor:
+              Theme.of(context).extension<StackColors>()!.buttonBackSecondary,
+          borderRadius: Constants.size.circularBorderRadius,
+          background:
+              Theme.of(context).extension<StackColors>()!.textFieldDefaultBG,
           onTap: () {
             if (!(ref.read(prefsChangeNotifierProvider).exchangeRateType ==
                     ExchangeRateType.estimated) &&
@@ -1503,127 +1331,17 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
             }
           },
           onChanged: receiveFieldOnChanged,
-          textAlign: TextAlign.right,
-          keyboardType: const TextInputType.numberWithOptions(
-            signed: false,
-            decimal: true,
-          ),
-          inputFormatters: [
-            // regex to validate a crypto amount with 8 decimal places
-            TextInputFormatter.withFunction((oldValue, newValue) =>
-                RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
-                        .hasMatch(newValue.text)
-                    ? newValue
-                    : oldValue),
-          ],
-          decoration: InputDecoration(
-            contentPadding: const EdgeInsets.only(
-              top: 12,
-              right: 12,
-            ),
-            hintText: "0",
-            hintStyle: STextStyles.fieldLabel(context).copyWith(
-              fontSize: 14,
-            ),
-            prefixIcon: FittedBox(
-              fit: BoxFit.scaleDown,
-              child: GestureDetector(
-                onTap: selectReceiveCurrency,
-                child: Container(
-                  color: Colors.transparent,
-                  child: Padding(
-                    padding: const EdgeInsets.all(12),
-                    child: Row(
-                      children: [
-                        Container(
-                          width: 18,
-                          height: 18,
-                          decoration: BoxDecoration(
-                            borderRadius: BorderRadius.circular(18),
-                          ),
-                          child: Builder(
-                            builder: (context) {
-                              final image = _fetchIconUrlFromTicker(ref.watch(
-                                  exchangeFormStateProvider
-                                      .select((value) => value.toTicker)));
-
-                              if (image != null && image.isNotEmpty) {
-                                return Center(
-                                  child: SvgPicture.network(
-                                    image,
-                                    height: 18,
-                                    placeholderBuilder: (_) => Container(
-                                      width: 18,
-                                      height: 18,
-                                      decoration: BoxDecoration(
-                                        color: Theme.of(context)
-                                            .extension<StackColors>()!
-                                            .textFieldDefaultBG,
-                                        borderRadius: BorderRadius.circular(18),
-                                      ),
-                                      child: ClipRRect(
-                                        borderRadius: BorderRadius.circular(
-                                          18,
-                                        ),
-                                        child: const LoadingIndicator(),
-                                      ),
-                                    ),
-                                  ),
-                                );
-                              } else {
-                                return Container(
-                                  width: 18,
-                                  height: 18,
-                                  decoration: BoxDecoration(
-                                    // color: Theme.of(context).extension<StackColors>()!.accentColorDark
-                                    borderRadius: BorderRadius.circular(18),
-                                  ),
-                                  child: SvgPicture.asset(
-                                    Assets.svg.circleQuestion,
-                                    width: 18,
-                                    height: 18,
-                                    color: Theme.of(context)
-                                        .extension<StackColors>()!
-                                        .textFieldDefaultBG,
-                                  ),
-                                );
-                              }
-                            },
-                          ),
-                        ),
-                        const SizedBox(
-                          width: 6,
-                        ),
-                        Text(
-                          ref.watch(exchangeFormStateProvider.select(
-                                  (value) => value.toTicker?.toUpperCase())) ??
-                              "-",
-                          style: STextStyles.smallMed14(context).copyWith(
-                            color: Theme.of(context)
-                                .extension<StackColors>()!
-                                .textDark,
-                          ),
-                        ),
-                        if (!isWalletCoin(coin, false))
-                          const SizedBox(
-                            width: 6,
-                          ),
-                        if (!isWalletCoin(coin, false))
-                          SvgPicture.asset(
-                            Assets.svg.chevronDown,
-                            width: 5,
-                            height: 2.5,
-                            color: Theme.of(context)
-                                .extension<StackColors>()!
-                                .textDark,
-                          ),
-                      ],
-                    ),
-                  ),
-                ),
-              ),
-            ),
-          ),
+          onButtonTap: selectReceiveCurrency,
+          isWalletCoin: isWalletCoin(coin, true),
+          image: _fetchIconUrlFromTicker(ref.watch(
+              exchangeFormStateProvider.select((value) => value.toTicker))),
+          ticker: ref.watch(
+              exchangeFormStateProvider.select((value) => value.toTicker)),
+          readOnly: ref.watch(prefsChangeNotifierProvider
+                      .select((value) => value.exchangeRateType)) ==
+                  ExchangeRateType.estimated ||
+              ref.watch(exchangeProvider).name ==
+                  SimpleSwapExchange.exchangeName,
         ),
         if (ref
                 .watch(
diff --git a/lib/widgets/textfields/exchange_textfield.dart b/lib/widgets/textfields/exchange_textfield.dart
new file mode 100644
index 000000000..8d3c5d699
--- /dev/null
+++ b/lib/widgets/textfields/exchange_textfield.dart
@@ -0,0 +1,384 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/loading_indicator.dart';
+
+class ExchangeTextField extends StatefulWidget {
+  const ExchangeTextField({
+    Key? key,
+    this.borderRadius = 0,
+    this.background,
+    required this.controller,
+    this.buttonColor,
+    required this.focusNode,
+    this.buttonContent,
+    required this.textStyle,
+    this.onButtonTap,
+    this.onChanged,
+    this.onSubmitted,
+    this.onTap,
+    required this.isWalletCoin,
+    this.image,
+    this.ticker,
+    this.readOnly = false,
+  }) : super(key: key);
+
+  final double borderRadius;
+  final Color? background;
+  final Color? buttonColor;
+  final Widget? buttonContent;
+  final TextEditingController controller;
+  final FocusNode focusNode;
+  final TextStyle textStyle;
+  final VoidCallback? onTap;
+  final VoidCallback? onButtonTap;
+  final void Function(String)? onChanged;
+  final void Function(String)? onSubmitted;
+
+  final bool isWalletCoin;
+  final bool readOnly;
+  final String? image;
+  final String? ticker;
+
+  @override
+  State<ExchangeTextField> createState() => _ExchangeTextFieldState();
+}
+
+class _ExchangeTextFieldState extends State<ExchangeTextField> {
+  late final TextEditingController controller;
+  late final FocusNode focusNode;
+  late final TextStyle textStyle;
+
+  late final double borderRadius;
+
+  late final Color? background;
+  late final Color? buttonColor;
+  late final Widget? buttonContent;
+  late final VoidCallback? onButtonTap;
+  late final VoidCallback? onTap;
+  late final void Function(String)? onChanged;
+  late final void Function(String)? onSubmitted;
+
+  @override
+  void initState() {
+    borderRadius = widget.borderRadius;
+    background = widget.background;
+    buttonColor = widget.buttonColor;
+    controller = widget.controller;
+    focusNode = widget.focusNode;
+    buttonContent = widget.buttonContent;
+    textStyle = widget.textStyle;
+    onButtonTap = widget.onButtonTap;
+    onChanged = widget.onChanged;
+    onSubmitted = widget.onSubmitted;
+    onTap = widget.onTap;
+
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      decoration: BoxDecoration(
+        color: background,
+        borderRadius: BorderRadius.circular(borderRadius),
+      ),
+      child: IntrinsicHeight(
+        child: Row(
+          crossAxisAlignment: CrossAxisAlignment.stretch,
+          children: [
+            Expanded(
+              child: TextField(
+                style: textStyle,
+                controller: controller,
+                focusNode: focusNode,
+                onChanged: onChanged,
+                onTap: onTap,
+                enableSuggestions: false,
+                autocorrect: false,
+                readOnly: widget.readOnly,
+                keyboardType: const TextInputType.numberWithOptions(
+                  signed: false,
+                  decimal: true,
+                ),
+                decoration: InputDecoration(
+                  contentPadding: const EdgeInsets.only(
+                    top: 12,
+                    left: 12,
+                  ),
+                  hintText: "0",
+                  hintStyle: STextStyles.fieldLabel(context).copyWith(
+                    fontSize: 14,
+                  ),
+                ),
+                inputFormatters: [
+                  // regex to validate a crypto amount with 8 decimal places
+                  TextInputFormatter.withFunction((oldValue, newValue) =>
+                      RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
+                              .hasMatch(newValue.text)
+                          ? newValue
+                          : oldValue),
+                ],
+              ),
+            ),
+            MouseRegion(
+              cursor: SystemMouseCursors.click,
+              child: GestureDetector(
+                onTap: () => onButtonTap?.call(),
+                child: Container(
+                  decoration: BoxDecoration(
+                    color: buttonColor,
+                    borderRadius: BorderRadius.horizontal(
+                      right: Radius.circular(
+                        borderRadius,
+                      ),
+                    ),
+                  ),
+                  child: Padding(
+                    padding: const EdgeInsets.symmetric(
+                      horizontal: 16,
+                    ),
+                    child: Row(
+                      children: [
+                        Container(
+                          width: 18,
+                          height: 18,
+                          decoration: BoxDecoration(
+                            borderRadius: BorderRadius.circular(18),
+                          ),
+                          child: Builder(
+                            builder: (context) {
+                              final image = widget.image;
+
+                              if (image != null && image.isNotEmpty) {
+                                return Center(
+                                  child: SvgPicture.network(
+                                    image,
+                                    height: 18,
+                                    placeholderBuilder: (_) => Container(
+                                      width: 18,
+                                      height: 18,
+                                      decoration: BoxDecoration(
+                                        color: Theme.of(context)
+                                            .extension<StackColors>()!
+                                            .textFieldDefaultBG,
+                                        borderRadius: BorderRadius.circular(
+                                          18,
+                                        ),
+                                      ),
+                                      child: ClipRRect(
+                                        borderRadius: BorderRadius.circular(
+                                          18,
+                                        ),
+                                        child: const LoadingIndicator(),
+                                      ),
+                                    ),
+                                  ),
+                                );
+                              } else {
+                                return Container(
+                                  width: 18,
+                                  height: 18,
+                                  decoration: BoxDecoration(
+                                    // color: Theme.of(context).extension<StackColors>()!.accentColorDark
+                                    borderRadius: BorderRadius.circular(18),
+                                  ),
+                                  child: SvgPicture.asset(
+                                    Assets.svg.circleQuestion,
+                                    width: 18,
+                                    height: 18,
+                                    color: Theme.of(context)
+                                        .extension<StackColors>()!
+                                        .textFieldDefaultBG,
+                                  ),
+                                );
+                              }
+                            },
+                          ),
+                        ),
+                        const SizedBox(
+                          width: 6,
+                        ),
+                        Text(
+                          widget.ticker ?? "-",
+                          style: STextStyles.smallMed14(context).copyWith(
+                            color: Theme.of(context)
+                                .extension<StackColors>()!
+                                .textDark,
+                          ),
+                        ),
+                        if (!widget.isWalletCoin)
+                          const SizedBox(
+                            width: 6,
+                          ),
+                        if (!widget.isWalletCoin)
+                          SvgPicture.asset(
+                            Assets.svg.chevronDown,
+                            width: 5,
+                            height: 2.5,
+                            color: Theme.of(context)
+                                .extension<StackColors>()!
+                                .textDark,
+                          ),
+                      ],
+                    ),
+                  ),
+                ),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
+
+// experimental  UNUSED
+// class ExchangeTextField extends StatefulWidget {
+//   const ExchangeTextField({
+//     Key? key,
+//     this.borderRadius = 0,
+//     this.background,
+//     required this.controller,
+//     this.buttonColor,
+//     required this.focusNode,
+//     this.buttonContent,
+//     required this.textStyle,
+//     this.onButtonTap,
+//     this.onChanged,
+//     this.onSubmitted,
+//   }) : super(key: key);
+//
+//   final double borderRadius;
+//   final Color? background;
+//   final Color? buttonColor;
+//   final Widget? buttonContent;
+//   final TextEditingController controller;
+//   final FocusNode focusNode;
+//   final TextStyle textStyle;
+//   final VoidCallback? onButtonTap;
+//   final void Function(String)? onChanged;
+//   final void Function(String)? onSubmitted;
+//
+//   @override
+//   State<ExchangeTextField> createState() => _ExchangeTextFieldState();
+// }
+//
+// class _ExchangeTextFieldState extends State<ExchangeTextField> {
+//   late final TextEditingController controller;
+//   late final FocusNode focusNode;
+//   late final TextStyle textStyle;
+//
+//   late final double borderRadius;
+//
+//   late final Color? background;
+//   late final Color? buttonColor;
+//   late final Widget? buttonContent;
+//   late final VoidCallback? onButtonTap;
+//   late final void Function(String)? onChanged;
+//   late final void Function(String)? onSubmitted;
+//
+//   @override
+//   void initState() {
+//     borderRadius = widget.borderRadius;
+//     background = widget.background;
+//     buttonColor = widget.buttonColor;
+//     controller = widget.controller;
+//     focusNode = widget.focusNode;
+//     buttonContent = widget.buttonContent;
+//     textStyle = widget.textStyle;
+//     onButtonTap = widget.onButtonTap;
+//     onChanged = widget.onChanged;
+//     onSubmitted = widget.onSubmitted;
+//
+//     super.initState();
+//   }
+//
+//   @override
+//   Widget build(BuildContext context) {
+//     return Container(
+//       decoration: BoxDecoration(
+//         color: background,
+//         borderRadius: BorderRadius.circular(borderRadius),
+//       ),
+//       child: IntrinsicHeight(
+//         child: Row(
+//           crossAxisAlignment: CrossAxisAlignment.stretch,
+//           children: [
+//             Expanded(
+//               child: MouseRegion(
+//                 cursor: SystemMouseCursors.text,
+//                 child: GestureDetector(
+//                   onTap: () {
+//                     //
+//                   },
+//                   child: Padding(
+//                     padding: const EdgeInsets.only(
+//                       left: 16,
+//                       top: 18,
+//                       bottom: 17,
+//                     ),
+//                     child: IgnorePointer(
+//                       ignoring: true,
+//                       child: EditableText(
+//                         controller: controller,
+//                         focusNode: focusNode,
+//                         style: textStyle,
+//                         onChanged: onChanged,
+//                         onSubmitted: onSubmitted,
+//                         onEditingComplete: () => print("lol"),
+//                         autocorrect: false,
+//                         enableSuggestions: false,
+//                         keyboardType: const TextInputType.numberWithOptions(
+//                           signed: false,
+//                           decimal: true,
+//                         ),
+//                         inputFormatters: [
+//                           // regex to validate a crypto amount with 8 decimal places
+//                           TextInputFormatter.withFunction((oldValue,
+//                                   newValue) =>
+//                               RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
+//                                       .hasMatch(newValue.text)
+//                                   ? newValue
+//                                   : oldValue),
+//                         ],
+//                         cursorColor: textStyle.color ??
+//                             Theme.of(context).backgroundColor,
+//                         backgroundCursorColor: background ?? Colors.transparent,
+//                       ),
+//                     ),
+//                   ),
+//                 ),
+//               ),
+//             ),
+//             MouseRegion(
+//               cursor: SystemMouseCursors.click,
+//               child: GestureDetector(
+//                 onTap: () => onButtonTap?.call(),
+//                 child: Container(
+//                   decoration: BoxDecoration(
+//                     color: buttonColor,
+//                     borderRadius: BorderRadius.horizontal(
+//                       right: Radius.circular(
+//                         borderRadius,
+//                       ),
+//                     ),
+//                   ),
+//                   child: Padding(
+//                     padding: const EdgeInsets.symmetric(
+//                       horizontal: 16,
+//                     ),
+//                     child: buttonContent,
+//                   ),
+//                 ),
+//               ),
+//             ),
+//           ],
+//         ),
+//       ),
+//     );
+//   }
+// }

From 0b6545645bdd7bdf1939c2de2b42397e47614210 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 14:55:26 -0600
Subject: [PATCH 092/100] macos + windows app icon

---
 .../AppIcon.appiconset/Contents.json          | 132 +++++++++---------
 .../AppIcon.appiconset/app_icon_1024.png      | Bin 46993 -> 69450 bytes
 .../AppIcon.appiconset/app_icon_128.png       | Bin 3276 -> 4664 bytes
 .../AppIcon.appiconset/app_icon_16.png        | Bin 1429 -> 926 bytes
 .../AppIcon.appiconset/app_icon_256.png       | Bin 5933 -> 10085 bytes
 .../AppIcon.appiconset/app_icon_32.png        | Bin 1243 -> 1441 bytes
 .../AppIcon.appiconset/app_icon_512.png       | Bin 14800 -> 26089 bytes
 .../AppIcon.appiconset/app_icon_64.png        | Bin 1874 -> 2443 bytes
 pubspec.lock                                  |   9 +-
 pubspec.yaml                                  |   9 +-
 windows/runner/resources/app_icon.ico         | Bin 33772 -> 1968 bytes
 11 files changed, 82 insertions(+), 68 deletions(-)

diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
index a2ec33f19..96d3fee1a 100644
--- a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,68 +1,68 @@
 {
-  "images" : [
-    {
-      "size" : "16x16",
-      "idiom" : "mac",
-      "filename" : "app_icon_16.png",
-      "scale" : "1x"
+    "info": {
+        "version": 1,
+        "author": "xcode"
     },
-    {
-      "size" : "16x16",
-      "idiom" : "mac",
-      "filename" : "app_icon_32.png",
-      "scale" : "2x"
-    },
-    {
-      "size" : "32x32",
-      "idiom" : "mac",
-      "filename" : "app_icon_32.png",
-      "scale" : "1x"
-    },
-    {
-      "size" : "32x32",
-      "idiom" : "mac",
-      "filename" : "app_icon_64.png",
-      "scale" : "2x"
-    },
-    {
-      "size" : "128x128",
-      "idiom" : "mac",
-      "filename" : "app_icon_128.png",
-      "scale" : "1x"
-    },
-    {
-      "size" : "128x128",
-      "idiom" : "mac",
-      "filename" : "app_icon_256.png",
-      "scale" : "2x"
-    },
-    {
-      "size" : "256x256",
-      "idiom" : "mac",
-      "filename" : "app_icon_256.png",
-      "scale" : "1x"
-    },
-    {
-      "size" : "256x256",
-      "idiom" : "mac",
-      "filename" : "app_icon_512.png",
-      "scale" : "2x"
-    },
-    {
-      "size" : "512x512",
-      "idiom" : "mac",
-      "filename" : "app_icon_512.png",
-      "scale" : "1x"
-    },
-    {
-      "size" : "512x512",
-      "idiom" : "mac",
-      "filename" : "app_icon_1024.png",
-      "scale" : "2x"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}
+    "images": [
+        {
+            "size": "16x16",
+            "idiom": "mac",
+            "filename": "app_icon_16.png",
+            "scale": "1x"
+        },
+        {
+            "size": "16x16",
+            "idiom": "mac",
+            "filename": "app_icon_32.png",
+            "scale": "2x"
+        },
+        {
+            "size": "32x32",
+            "idiom": "mac",
+            "filename": "app_icon_32.png",
+            "scale": "1x"
+        },
+        {
+            "size": "32x32",
+            "idiom": "mac",
+            "filename": "app_icon_64.png",
+            "scale": "2x"
+        },
+        {
+            "size": "128x128",
+            "idiom": "mac",
+            "filename": "app_icon_128.png",
+            "scale": "1x"
+        },
+        {
+            "size": "128x128",
+            "idiom": "mac",
+            "filename": "app_icon_256.png",
+            "scale": "2x"
+        },
+        {
+            "size": "256x256",
+            "idiom": "mac",
+            "filename": "app_icon_256.png",
+            "scale": "1x"
+        },
+        {
+            "size": "256x256",
+            "idiom": "mac",
+            "filename": "app_icon_512.png",
+            "scale": "2x"
+        },
+        {
+            "size": "512x512",
+            "idiom": "mac",
+            "filename": "app_icon_512.png",
+            "scale": "1x"
+        },
+        {
+            "size": "512x512",
+            "idiom": "mac",
+            "filename": "app_icon_1024.png",
+            "scale": "2x"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
index 3c4935a7ca84f0976aca34b7f2895d65fb94d1ea..55efad011aa22c651bd4eeb225bebd9c6fea31bd 100644
GIT binary patch
literal 69450
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
PKlPC5u>%Drr*HfpG~rAC

literal 46993
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
QOu#(cH>|q6Qt;3J0APUL!~g&Q

diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
index ed4cc16421680a50164ba74381b4b35ceaa0ccfc..c8ba3b1a21bf014a0ed55ac2169dc48b4abb240f 100644
GIT binary patch
literal 4664
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
Lx+=BLUw-%>(J$+(

literal 3276
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

diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
index 483be61389733f2e5331c08db8ca245268610ccb..e85f014180ccfa3df01d669e08620973393bc259 100644
GIT binary patch
delta 915
zcmV;E18n@23!Vp%8Gi-<001BJ|6u?C0fcEoLr_UWLm+T+Z)Rz1WdHzpoPCi!NW(xJ
z#a~lPRazA6AmWgrI$01Eanvdlp+cw?T6HkF^b49aBq=VAf@{ISkHxBki?gl{u7V)=
z0pjT7r060g{x2!Ci1pyOAMfrx?%n}Hz05SLYaGyY+e{_mVt*#PDh6K>L>T=Dphsqw
zF(*k$bR1vz@bUF7#<Mz~`*VcVoW%g2NIc67(<a^^p5C+#&ilj>R+LrZbK)_RE=c^y
zb;aX1&IOkRo*6OIsd?fEu~=whrHxt9)QG2uqpGG;zL4=)<-EmND_2?bp8SQOoW8Qm
zb(+ISU=d4@Ab&zZ6(y8mBSx!EiiH&I$2<6kT)#vvg<K^tax9<%4YKP8|AXJ%TKUNd
zFDVoU0xyp9F#-g4fkw@7zK<QJaRT_Cfh)b`uhfB=Ptt2GEqVm>Z37qAElt@2E_Z;z
zCqp)6SMt*o@_FF>jJ_!g4BP^}YhG{7eVjf3Y3eF@1AiPG0;2`WUhnYk?)KjPJ=5&(
z2kcmKaYeY=jQ{`v)k#D_RCocUQ@gHdQ4}56B;py7NIc`&_yCQ{2PhPXLL*VAG!z=O
zs5KgeLR1>1L?aS9BGD+sBOwxm#9Q1uSF-nc+<Wf1$r;UFd#y3YoO7(Xxbyk^!Vkdx
zB=}o_&3|Tt)oKN$QVFZo3W-GWe*(MR4$Wp0r_%{erxWY-8q4JpE|&`ig8?Fu=<fp8
z>lLk53+;9r_xl}oyInZDTrL=mMp!Hs@OV5>tJQA;uh$E`UXNux9*;uMY&L_<W`jzl
z6884{J^KAVj7B4?j+@Wt$mjE{Y_r)6u~;mSpMTFMI-L&OZZ{kb$A>d&?{>R^t5hmX
zkwE1US+Ca%eLfx!jK^bEjo0gCW)g?@f};hG-!p;Xa0s1F$4KNpkHg`BTCE0?$%Je+
zD<t3|kq8=%2FuQ4yWO&?h)hP(|70>@CQqkRghC-iqfw+%DR5e?7WH}^rBaD~sc+s`
z5`U%ZqxE|bXD}GBb9M_FjRv_~4&iVZg+c+{ZdWMrb1?anPNxwJ2AQcJ=70vJTrRUY
zC>D#L8{#3AN)eC8kxV9`P$-1`KPHhf2Lb{3{eD!dRVL{3`H;zEV6j*})4zTTGMNmC
pL;|r`405^rE86$3@n6A&Ut0#p@f^_w=nMb=002ovPDHLkV1iY&s4f5i

literal 1429
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F
z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a><YADU|^aU;1l8sRFH7;2N1=B
zQQV0iv0xN^;z#sxC`vr}6NoU?!~oTRQPlAta5Zq#;6?$JK~=((;W7=P3}^zxG`N{)
zZUedys1hg$u?tff&}tw`Joy9Yut*q!D29`8Ga>GbI`Jdw*pG<g2rUo=$RxyAi0zQ@
zK{g*#CB!bc_u+~|kN*O?3St_>cA%L+*Q#&*YQOJ$_%U#(BDn<O1)%wG2LRc++rJs_
z{ARTCo88{;VIVC(fy&@kKq3(+!cg`Os0N4(foRuvi_Pzx*E}+qe75q_|L~(AaRZ1H
zSXO7vE8*g;>``;rKxi&&)LfRxIZ*98z8UWRslDo@Xu)QVh}rB>bKwe@Bjzwg%m$hd
zG)gFMgHZlPxGcm3paLLb44<vP<D2@r*P^96AbR1lK<$hXvw`IQ|Nj*t=9vH!<*kw+
zKTrZ^aK8WT>yHI|Ag0wdp!_yD5R<|B29Ui~27`?vfy#ktk_KyHWMDA42{J=Uq-o}i
z*%kZ@45mQ-Rw?0?K+z{&5KFc}xc5Q%1PFAbL_xCmpj?JNAm>L6SjrCMpiK}5LG0ZE
z<A9vK72<4{``^ETd}9%0zzx*KnB?v5a_b$lS`(1NS>O>_%)r1c48n{Iv*t(u1=&kH
zeO=ifbFy+6aSK)V_5t;<dAc};NL)@%U|@7pOA`w-E93Li%QKkYKD|HQA;2TTCB#SO
z$n*(QCQX|-b#iz>NKhE#$Iz=+Oii|KDJ}W>g}0%`Svgra*tnS6TRU4iTH*e=dj~I`
zym|EM*}I1?pT2#3`oZ(|3I-Y$DkeHMN=8~%YSR?;>=X?(Emci*ZIz9+t<|S1>hE8$
zVa1LmTh{DZv}x6@Wz!a}+qZDz%AHHMuHCzM^XlEpr!QPzf9Qzk<mEnd&1#RGiQN30
zVeL%o{C`cY-D3KYyK;VZO-*PwUK6!9?d`6w(q?(L_M~b@B;5WcYhC{K-sbZA|CrhN
z8(sP2Evw%A=$yRVZ@y(U-=dd)TDzy~#qX?o`>S_0!&1MPx*ICxe}RFdTH+c}l9E`G
zYL#4+3Zxi}3=A!G4S>ir#L(2r)WFKnP}jiR%D`ZOPH`@ZhTQy=%(P0}8ZH)|z6jL7
N;OXk;vd$@?2>?>Ex^Vyi

diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
index bcbf36df2f2aaaa0a63c7dabc94e600184229d0d..bfb090fc604d253944fcabee1e019ee460c70201 100644
GIT binary patch
literal 10085
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

literal 5933
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

diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
index 9c0a652864769b250ed58097f2f6270b393f751f..877b87dc389f3f83852a0eaf258bbeea9122221c 100644
GIT binary patch
delta 1424
zcmV;B1#kM>384#+BYy#eX+uL$Nkc;*aB^>EX>4Tx0C=2zkv&MmKpe$iQ%hA^6zm}4
zkfAzR5EXIMDionYs1;guFuC*#nlvOSE{=k0!NHHks)LKOt`4q(Aou~|=;Wm6A|?JW
zDYS_7;J6>}?mh0_0YbgZG^=YI&~)2OCE{WxyDA1>5kwgM2!EhQW|lE0NlA1ZU-$6w
z^)AM<I-mP<gw>qI0G~)a%M8;d-XNadv<=St#1U4MRpN8vF_SJx{K$31<2TL)mj#{~
zG1IAe;s~)=Xk(>~S<%#pr--Afrc=I<@mS@&#aSy?S@WL!g`u3jvdndw!$@EeOOPN!
zK@}yGVIxMXPJfDp6z#`5_=jA-L@tF~B`|U<paKoD>j(dX-`!gI$q6qh6bAw?j`J}B
z1b2Z(&2heu9j9>u_@99*z2&deftgRzYb`B$1oUkK7uPLK*#j<jfWaq2Hf2}x(-iV~
z;QfrgDGLnT0=;WqZ_Rz2J^*RzDtQAO90H>S%3kmA?tkv~-u^w)?C%HcSaNYixY~^X
z00Y=bL_t(|0qs{=C}v?8esJuRec#taaxcwDjZ%u#Fg2q@8C(#GJC`UUxp5<z6uFQT
zV&=vL5xF2)BeJjA_hruWO~3j19sjY+xS8k1a=!Du&-cF1`@G+gPEJm4@P?4yGWdT2
zuR>sNZ+{Q_`}?rAwuX(3&A%hCxw(n)@o`*ST!_DKZf@Y{=!l@8AXr#f{5=B4$H(aI
z?#95t0AgZdU}$J4{%>GlfUT`9Y;SMF%gYPCzP^wo{oAW1aCv!&zP>(mb#)06mX?;c
z!L`9mEG#Twb!7$q0ReDxa}(sAO@JGYjg6tLt$$6VU4zrpQ(RwPKS+W&mrFA-F@eR!
zMFa;2!`9aJ=>(RRmeAVTikX=iol{(0T?s<Y&d!e>;PCJe!^6XHa&kgoU?9xR&Gi%5
z+ucQbM+b(6hC~LGQaCj=C4{Gx1#N6>YzU1|A3i=lxB9q4fOYQa=@BA3KR?&IDO+%K
zbbl1#;o+)Cuw?V|^H^P7MS!di7Z;a51p52?(a_L<v$Hc;Sy}1bOas>V;NSpZVPT4O
zz7NJ=Htg-~e-o&vs6c&v{p|u*S6BG^`@_`KRMm#Na>;sod*R{Xfsl|8n3<U=uBBno
zD>P&!3QapW!4$D(-rnA#W=2Lvs)%qezJJRA^a1VnjE#*&+V8iew6?bP;AT|$+}s>i
z<bLLhRPkf|to<I_k6sWO8Y;5s>FEhSKfec!Ng|`il+J#q576g%GNw=sj*gDd+1V)!
ztEi|*(G?{!WZfnwCm-FAbsiiXguA=DIE{&kiQ-!J{`B-Tc6N5e!IF}ako@r@vVU`O
zbOx5h1-ZGo$jZu6b+YB<Wvs8SiyBjO+U>`|#IkXXc2-%I#-=88$QjAb&PH-_@?9T@
zii$#BULLBds#KAnU(g*Hi0)=*XD5DVa6VH4eWSFr6wS@eqAZb-k$-$3BO^nUqP)CZ
zY@`MpN+Tm9LgAXRtOm2Qv-mD|9)IKAQ3e^cw6vf}PFGD$jW8HBcuH`#bzxy4qNAfl
ziFBmN)1;=RB0fGI)z#I45H0kj;3eg2W+py=`Ep0ViqnuzRZ>!dPbn!VEh`fppvDL8
zgYP6HBnY89I5_A$*Lxobl4p5cT^)Y@_<?Vgl|pQ45fKrA;^Ja4CzPP-Mt{Upe29(3
zyZ7&fZP(V;LjIspT+cf~ettgU;^OpX?MZh+4yR1Hj){qhsFbtO-rlbBJS{B^>FMb@
z7mrsVpaJJXnXHQxSs(mKtB#d3R8UYLhRsv(qVEFMxUsQOTrz0S&%uj7OlZZ=4gM+w
eUWzv-@C)B~n#-8vW6l5o00{s|MNUMnLSTXy*2F#l

delta 1224
zcmV;(1ULJk3)=~hBYyw{XF*Lt006O%3;baP0000WV@Og>004R>004l5008;`004mK
z004C`008P>0026e000+ooVrmw00006VoOIv0RI600RN!9r;`8x010qNS#tmY3ljhU
z3ljkVnw%H_000McNliru;|T=_G7A!Wjg9~S1IkH6K~z}7t$&wYXdG1($A4#b8}k9i
z6oeKZ#P&&qlI)X$Amqiq`Dz7CgPVW|f)IT2t%#_hFMZ4g#MY*dRbMoOAcdADh?Jrw
zCEB!!RQn+{A3NPmcIWtT=T7d-?(EKPdtsTGd*`0t|D1F0xjRCaZEUFusC^s)&Zu%+
zA+Vk5UX>hhLw{icSULY%F97*&;3t===sx^e;B(*v;H6Fy?x36!SaG}4C$xZrBKz>K
zfXOzt)_@|yd~%>80pszoTlfT6J*n_XV8KrPHVl790t_6)usVmE$uT%&Tmu%~spsOt
zfpf3+HoVj}0$Jgzv1yU#w!0a;t$=Pl$MIZRz*`DPgMTY3;4DQq3dx)UXIsEi1#}7z
z!{0I7M(C-+?RXYAK+b(Q>FjesGKKv~;IRmdEme^gMW$)awK449bO4V8jKw^U!&AJD
z!3A>y#SWkFrlBuvbMeC{8Xi>mk~Ui{>3Q9}{1R}K)J#S8t^@aNr&|g8fiFVCX<$gK
zb~ToV6@O-cW6^QkD8mCT0w1}Z$x__ZYp2S^;K4q87AQ2#i(kJ7J_hb3RoUhPp8zFQ
z1GT>-yvKtLU&%=vu1Rtn{sC||DKZuTRW^aC@UiF^SOX>n7HSGN{|itU-r8e!ATLef
zj)n&KoO2>N+prROt1t*mhazrc7Ue=+;pSEVFn<ip_IMNy^$GoXX$sdi@P?efceUag
zcrHxI&%k^V4ipqP;KAWOVIU_R!y5zuyc>#e#<i}nvK1g9T%84{K#vE9dxe3#DP>vV
zO$8)HlxuLi9DsqAfRRLwA&P{@Kwd7Y>W5k2sRG<q_{q1op8}^+D<eYn@4J=q>gxEx
zLx0a-xOVz$dS5S4IXm9cekK87u^9@hWU(21XZ<h!S^kAR-~UrYCV|BuFmiX#zn^M9
z)1Oi?A%BF~qNNC|2423i!Tl@C)ON}Ua#U4kRCQEB_YS->+r5Ba-|Tnuy$MXInqq|r
z{@OYZFI}a+y%P#mfFr8Rs4{9N=1-KG+JA4G0^3HywO~H8WDs<^ytZC^aCw>C-3me8
zLqnIHdU6X>Ll!mctj)zUm{|b8@Q+5s-u4a}1cMv%i_^Q0{UQl)Bot89Tfl@Wi*~Gj
zVP8Z?Uq;uC_uCIm9<Bbd>2GaLAyRVB42{D9j$ls8QTsjVy*(4z%w>h!cJJJ0Y=1xV
zGLIiTM7&%TxC9&oM%0O@4S9GO0^R^_VA6vA_Ct390BYC2BY*5I`&d=D0=x*kpsHoe
z$?B_`E8r{I2fU)nW#C_aHv;|#93kSZ<%JtK0000bbVXQnWMOn=I%9HWVRU5xGB7bY
zEigGPFf~*$H99pgIx#UVFgH3dFhQU!b8P?s03~!qSaf7zbY(hiZ)9m^c>ppnF*z+T
mIV~_XR53L=H846cF)c7RIxsNNam&#F0000<MNUMnLSTZ9Sr(fB

diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
index e71a726136a47ed24125c7efc79d68a4a01961b4..f24fbe65de8627a88836014c48b7f8156a627594 100644
GIT binary patch
literal 26089
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
BO?v<U

literal 14800
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
OIc;`vc)7{z(*FShbtRtw

diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
index 8a31fe2dd3f91d79cab6e0390356bb3c1a355f94..b81789038bb1b5e0704d296cdcab37af92284870 100644
GIT binary patch
delta 2433
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

delta 1860
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

diff --git a/pubspec.lock b/pubspec.lock
index 0b8f49c2c..f12b25487 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -205,6 +205,13 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.0.1"
+  cli_util:
+    dependency: transitive
+    description:
+      name: cli_util
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.3.5"
   clock:
     dependency: transitive
     description:
@@ -494,7 +501,7 @@ packages:
       name: flutter_launcher_icons
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.9.3"
+    version: "0.11.0"
   flutter_libepiccash:
     dependency: "direct main"
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index af4370d99..b1312427d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -141,7 +141,7 @@ dev_dependencies:
   integration_test:
       sdk: flutter
   build_runner: ^2.1.7
-  flutter_launcher_icons: ^0.9.3
+  flutter_launcher_icons: ^0.11.0
   hive_generator: ^1.1.2
   dependency_validator: ^3.1.2
   hive_test: ^1.0.1
@@ -160,6 +160,13 @@ flutter_icons:
   image_path_android: assets/icon/app_icon_alpha.png
   image_path_ios: assets/icon/icon.png
   remove_alpha_ios: true
+  windows:
+    generate: true
+    image_path: assets/icon/icon.png
+    icon_size: 48 # min:48, max:256, default: 48
+  macos:
+    generate: true
+    image_path: assets/icon/icon.png
 
 flutter_native_splash:
   image: assets/images/splash.png
diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico
index c04e20caf6370ebb9253ad831cc31de4a9c965f6..eee73d91b8f7daeadfb6dcb917cdb15466910278 100644
GIT binary patch
literal 1968
zcmV;h2T%9_0096205C8B0000W0GbB?02TlM0EtjeM-2)Z3IG5A4M|8uQUCw|FaQ7m
zFbD<!00374`G)`i0fcEoLr_UWLm+T+Z)Rz1WdHzpoPCi!NW(xJ#a~lPRazA6AmWgr
zI$01Eanvdlp+cw?T6HkF^b49aBq=VAf@{ISkHxBki?gl{u7V)=0pjT7r060g{x2!C
zi1pyOAMfrx?%n}Hz05SLYaGyY+e{_mVkWyP244|G82t#KM`o5WCrL?k9AEeF@%1jo
zvpS#qbA;8L#Q>j3Jj)EzCf*>P-n0$Q`@|7elvUz$;xUshNc_lk#p5^51(yY$88OqT
zdEyAMSZHIVjakvuh^L67s-{!EknvdMyv127S6TC({Dq;MzOu}9n!`w75lfIDLO~TJ
zlwl)At4@lA6z#`5_=jA-L@tF~B`|U<paKoD>j(dX-`!gI$q6qh6bAw?j`J}B1b2Z(
z&2heu9j9>u_@99*z2&deftgRzYb`B$1oUkK7uPLK*#j<jfWaq2Hf2}x(-iV~;Qfrg
zDGLnT0=;WqZ_Rz2J^*RzDtQAO90H>S%3kmA?(X*9{yo#|?+5Hya&bkt+Km7J1<^@F
zK~#7F?O9n!RcjPpnq!*gkecOC8IB~F+#Xd#gpfc)Q!@wyt*0{eC7~XAXwXm`9_-$<
z(i@`YfQS!eg%y}3g;?U4XoIOa<B-$c-{PLG9?v=Mv-h#X1wRm{z5oCJ*6^*h{$n&Z
zH@8avV;JfC0CKTSK;PIVpl|#Z0xK&kw7k4b#>U1vUwcalOixc!e}6xXjEpb=Gcz-C
zad9D6S64DLG}Or+TS8!Vc9t3&8~JB*b94S~U|>KC3k%fK(?egrd?61H4{~sD;J?d(
zP6@!uFJHc-hK2@ma&jU+KR=bv3B{Az+S<s*#)iDTy~)DDLh_zEA+Wl-N*x^?R99C=
zU%!6kzu|D20LxEIOi*)kGwt8MpAH;2Kqe+8TJJ5Jz`(!&)zs8*Xsitfv7rI-gM)+g
z?b|mxc<>;T(I!766PTKsVvD!5wD9lB2S%7^gQcY<>gwuZGG3mZWM^+L>OHLq{QUWo
znwpyE@#DudKR>Vbxv{Y^I&|oew#zf|ckkbGf+Nv)?%b*IdC>%*<%m}#D6GF3hKGk)
zbxci7#cr|TeaP>=ef!uD>S~B60)2gbR8>{Q@h&#DLAbZKmwbGD#GhIT$dAvTKhyW`
z-`N|^&dwY5*GS;Uj~`T9TTAZ+m*PcjH5<ec3icx7SsfM^7g^;%##6|T-Me@H`kzVy
zaQ%}fPw3gRXZ*6%Vgm~z$pZrenTTAVvcG-%miFw~!yZBX*g)XJhYwU%RwgRW#Q?<(
zB(UM(!-r|djvcbsL~fvFczJpKM*#7C<Hiko@!|zr&eGD7+}+)EQtq){cXv0305(Np
zN?jA-14CF_Tl4Qs02!Z<kigQXz|71HwYRtPgRtJ(xRVN&$an9!!9#M}+S-bK7d;i!
z$kEYp9eE~DR8+L?@M|$SIZ3Upt^6XGOO?g77#|;}SFc{NCwzT<HLi)nqRl`wsH)IR
z04lQ?AZ4SYqvYo1#_g~!Vi{d2ybr_RfXZu%DP~Lni6#bk4$`P-hn3wa1yH$<A3y#I
zD|E34Tgas%&NYDv;2_Xhv4G4%trWVvYu7I64E_aX2!s^~Wn^TCIy}Gx0s;c)`Sa&m
zZ;JeQ^X3i5veb4MK-ESQ_vzCo_HtBI6eXNGMM=rYn;M4+96x@Xa&vRJBh(g(a*uWx
zag32sY<}R~p`jseIp9?V;DzFQ_vq21M@-_BKt^LPgt&{0jHHT+3atq!0L$SZ7-$ey
zc6N3epNC9$c6PENsmr4&q4H*BWl?o?HDz4BOn)3ZrkVhdl9EENU%%#pCI`@Zs2T`B
zU6jW~wBry05QPWChyV<ec=jxXhK5pFS{i$K0|6^5D=IE7rt{~|^I#ztXarGP6#0R$
zLa0G)q=YJfivr9dv9Ym~l$69{>$+YDYE)WUN?DniR8d*U7Lo%+ejv_`jEpo6Kw^RX
zc<|r>_d}V&IX5(OC>mF;UZt3mCn@vREov6RO0L$!;!>@y3<yPPYAOW>2lKhq&I4$=
z{<?dYo<4m_+1c6bdVRuL2=U}|=O{itp1rAn#(@S5kvKs?K^$6nd3o#P?sp+3CWbCv
zyvTW~3{fK`7@s+FhQh+aC_g`+>g(&d_-rMRKNy5AUAjd6{{HIErp=;Il<U{8)9KTv
zd3HdTDmOn=0Wt}>g!eatq<bMWUH9+bXHVR|eVY|Q7r^CjVqzkl6*OOL+b;QH3zm<F
zh@g;=5GpJzq>_>nmN=;h4-aRn@7=pstM_DIEuzvQPUGU@C?_X}y&@Kfb2O6a>FIRj
z$Pr2V>+E(Kmb-cLCM(9ZYuEU$R1+|w;@~GvoRF1AI{$p&=+UE8DOB<D@^UIDDBzZR
zEznhB{!SLUOk5nu#g=@)0og^tL5}=+=MMe-@F6#Gi1P~<F7QaIv%Pe-k_w>kqzZ`{
z9UV<0!aNP{=o-J}Lq1nr1PEVSf$fi3^^I);`o=%vDvS@J%kMY<0000<MNUMnLSTZ$
CG^h~(

literal 33772
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


From a8b0901ec664e9f1bee21222cd5d4e319e92aeff Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 15:32:06 -0600
Subject: [PATCH 093/100] desktop exchange navigation flow fix

---
 lib/pages/exchange_view/confirm_change_now_send.dart | 12 ++++++++++++
 lib/pages/exchange_view/send_from_view.dart          |  6 ++++++
 .../exchange_steps/subwidgets/desktop_step_4.dart    |  1 +
 3 files changed, 19 insertions(+)

diff --git a/lib/pages/exchange_view/confirm_change_now_send.dart b/lib/pages/exchange_view/confirm_change_now_send.dart
index 9f62bd8ec..540067915 100644
--- a/lib/pages/exchange_view/confirm_change_now_send.dart
+++ b/lib/pages/exchange_view/confirm_change_now_send.dart
@@ -37,6 +37,7 @@ class ConfirmChangeNowSendView extends ConsumerStatefulWidget {
     this.routeOnSuccessName = WalletView.routeName,
     required this.trade,
     this.shouldSendPublicFiroFunds,
+    this.fromDesktopStep4 = false,
   }) : super(key: key);
 
   static const String routeName = "/confirmChangeNowSend";
@@ -46,6 +47,7 @@ class ConfirmChangeNowSendView extends ConsumerStatefulWidget {
   final String routeOnSuccessName;
   final Trade trade;
   final bool? shouldSendPublicFiroFunds;
+  final bool fromDesktopStep4;
 
   @override
   ConsumerState<ConfirmChangeNowSendView> createState() =>
@@ -105,7 +107,17 @@ class _ConfirmChangeNowSendViewState
       if (mounted) {
         if (Util.isDesktop) {
           Navigator.of(context, rootNavigator: true).pop();
+
+          // stupid hack
+          if (widget.fromDesktopStep4) {
+            Navigator.of(context, rootNavigator: true).pop();
+            Navigator.of(context, rootNavigator: true).pop();
+            Navigator.of(context, rootNavigator: true).pop();
+            Navigator.of(context, rootNavigator: true).pop();
+            Navigator.of(context, rootNavigator: true).pop();
+          }
         }
+
         Navigator.of(context).popUntil(ModalRoute.withName(routeOnSuccessName));
       }
     } catch (e) {
diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart
index 7cbf38384..7c5f5541c 100644
--- a/lib/pages/exchange_view/send_from_view.dart
+++ b/lib/pages/exchange_view/send_from_view.dart
@@ -38,6 +38,7 @@ class SendFromView extends ConsumerStatefulWidget {
     required this.amount,
     required this.address,
     this.shouldPopRoot = false,
+    this.fromDesktopStep4 = false,
   }) : super(key: key);
 
   static const String routeName = "/sendFrom";
@@ -47,6 +48,7 @@ class SendFromView extends ConsumerStatefulWidget {
   final String address;
   final Trade trade;
   final bool shouldPopRoot;
+  final bool fromDesktopStep4;
 
   @override
   ConsumerState<SendFromView> createState() => _SendFromViewState();
@@ -191,6 +193,7 @@ class _SendFromViewState extends ConsumerState<SendFromView> {
                       amount: amount,
                       address: address,
                       trade: trade,
+                      fromDesktopStep4: widget.fromDesktopStep4,
                     ),
                   );
                 },
@@ -210,12 +213,14 @@ class SendFromCard extends ConsumerStatefulWidget {
     required this.amount,
     required this.address,
     required this.trade,
+    this.fromDesktopStep4 = false,
   }) : super(key: key);
 
   final String walletId;
   final Decimal amount;
   final String address;
   final Trade trade;
+  final bool fromDesktopStep4;
 
   @override
   ConsumerState<SendFromCard> createState() => _SendFromCardState();
@@ -323,6 +328,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
                     : HomeView.routeName,
                 trade: trade,
                 shouldSendPublicFiroFunds: shouldSendPublicFiroFunds,
+                fromDesktopStep4: widget.fromDesktopStep4,
               ),
               settings: const RouteSettings(
                 name: ConfirmChangeNowSendView.routeName,
diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
index c86713a76..5b69f064d 100644
--- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_4.dart
@@ -224,6 +224,7 @@ class _DesktopStep4State extends ConsumerState<DesktopStep4> {
                                 amount: amount,
                                 address: address,
                                 shouldPopRoot: true,
+                                fromDesktopStep4: true,
                               ),
                               const RouteSettings(
                                 name: SendFromView.routeName,

From c3a3dd3180358f0f1e2faae0cf16c6d7a8b4ecb4 Mon Sep 17 00:00:00 2001
From: sneurlax <sneurlax@gmail.com>
Date: Tue, 22 Nov 2022 11:48:52 -0600
Subject: [PATCH 094/100] remove Wownero if isDesktop

or isLinux or isWindows or isMacOS, respectively
---
 .../add_wallet_view/sub_widgets/searchable_coin_list.dart    | 5 +++++
 lib/utilities/enums/coin_enum.dart                           | 4 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/searchable_coin_list.dart b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/searchable_coin_list.dart
index d89d42bbf..38181b9e1 100644
--- a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/searchable_coin_list.dart
+++ b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/searchable_coin_list.dart
@@ -32,6 +32,11 @@ class SearchableCoinList extends ConsumerWidget {
     // remove firo testnet regardless
     _coins.remove(Coin.firoTestNet);
 
+    // Kidgloves for Wownero on desktop
+    if(isDesktop) {
+      _coins.remove(Coin.wownero);
+    }
+
     return _coins;
   }
 
diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart
index 48212bde8..f80c40f52 100644
--- a/lib/utilities/enums/coin_enum.dart
+++ b/lib/utilities/enums/coin_enum.dart
@@ -12,6 +12,7 @@ import 'package:stackwallet/services/coins/monero/monero_wallet.dart' as xmr;
 import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart'
     as nmc;
 import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart' as wow;
+import 'dart:io' show Platform;
 
 enum Coin {
   bitcoin,
@@ -36,8 +37,7 @@ enum Coin {
   firoTestNet,
 }
 
-// remove firotestnet for now
-const int kTestNetCoinCount = 4;
+int kTestNetCoinCount = (Platform.isLinux || Platform.isWindows || Platform.isMacOS) ? 5 : 4;
 
 extension CoinExt on Coin {
   String get prettyName {

From 3306cf8b99f4afd54030bdef8746eb5de89adf6c Mon Sep 17 00:00:00 2001
From: sneurlax <sneurlax@gmail.com>
Date: Tue, 22 Nov 2022 11:56:13 -0600
Subject: [PATCH 095/100] expand the ternary for readability

---
 lib/utilities/enums/coin_enum.dart | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart
index f80c40f52..648407809 100644
--- a/lib/utilities/enums/coin_enum.dart
+++ b/lib/utilities/enums/coin_enum.dart
@@ -37,7 +37,12 @@ enum Coin {
   firoTestNet,
 }
 
-int kTestNetCoinCount = (Platform.isLinux || Platform.isWindows || Platform.isMacOS) ? 5 : 4;
+if(Platform.isLinux || Platform.isWindows || Platform.isMacOS) {
+  int kTestNetCoinCount = 5; // Because we are removing Wownero from Desktop
+} else {
+  // remove firotestnet for now
+  int kTestNetCoinCount = 4;
+}
 
 extension CoinExt on Coin {
   String get prettyName {

From 172b3d157bacc84dff2dece8b4fd0c11ca9e1487 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 15:37:47 -0600
Subject: [PATCH 096/100] wownero disable on desktop fix

---
 lib/utilities/enums/coin_enum.dart | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart
index 648407809..543a193ee 100644
--- a/lib/utilities/enums/coin_enum.dart
+++ b/lib/utilities/enums/coin_enum.dart
@@ -12,7 +12,7 @@ import 'package:stackwallet/services/coins/monero/monero_wallet.dart' as xmr;
 import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart'
     as nmc;
 import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart' as wow;
-import 'dart:io' show Platform;
+import 'package:stackwallet/utilities/util.dart';
 
 enum Coin {
   bitcoin,
@@ -37,12 +37,7 @@ enum Coin {
   firoTestNet,
 }
 
-if(Platform.isLinux || Platform.isWindows || Platform.isMacOS) {
-  int kTestNetCoinCount = 5; // Because we are removing Wownero from Desktop
-} else {
-  // remove firotestnet for now
-  int kTestNetCoinCount = 4;
-}
+final int kTestNetCoinCount = Util.isDesktop ? 5 : 4;
 
 extension CoinExt on Coin {
   String get prettyName {

From 157829a933da78229e6279aeb3ae1fcc8409307b Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 15:53:16 -0600
Subject: [PATCH 097/100] fixed failing test

---
 test/widget_tests/address_book_card_test.dart | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/widget_tests/address_book_card_test.dart b/test/widget_tests/address_book_card_test.dart
index 7c53d8d50..07b1387df 100644
--- a/test/widget_tests/address_book_card_test.dart
+++ b/test/widget_tests/address_book_card_test.dart
@@ -70,7 +70,7 @@ void main() {
       await widgetTester.tap(find.byType(RawMaterialButton));
       expect(find.byType(ContactPopUp), findsOneWidget);
     } else if (Util.isDesktop) {
-      expect(find.byType(RawMaterialButton), findsOneWidget);
+      expect(find.byType(RawMaterialButton), findsNothing);
     }
   });
 }

From 467d43d9f3c3c80b4dfc03c8232b56bcefeebc1d Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 16:18:38 -0600
Subject: [PATCH 098/100] desktop trade history scroll fix

---
 .../desktop_exchange_view.dart                |  16 +-
 .../subwidgets/desktop_trade_history.dart     | 368 ++++++++++--------
 2 files changed, 217 insertions(+), 167 deletions(-)

diff --git a/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart b/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart
index 0f44eb59b..105c485f0 100644
--- a/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart
@@ -63,19 +63,9 @@ class _DesktopExchangeViewState extends State<DesktopExchangeView> {
               width: 16,
             ),
             Expanded(
-              child: Column(
-                mainAxisSize: MainAxisSize.min,
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  Text(
-                    "Exchange details",
-                    style: STextStyles.desktopTextExtraExtraSmall(context),
-                  ),
-                  const SizedBox(
-                    height: 16,
-                  ),
-                  const RoundedWhiteContainer(
-                    padding: EdgeInsets.all(0),
+              child: Row(
+                children: const [
+                  Expanded(
                     child: DesktopTradeHistory(),
                   ),
                 ],
diff --git a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
index a8f825911..e31a87dd4 100644
--- a/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
+++ b/lib/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart
@@ -6,6 +6,7 @@ import 'package:stackwallet/pages/exchange_view/trade_details_view.dart';
 import 'package:stackwallet/providers/exchange/trade_sent_from_stack_lookup_provider.dart';
 import 'package:stackwallet/providers/global/trades_service_provider.dart';
 import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/utilities/constants.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
 import 'package:stackwallet/widgets/rounded_white_container.dart';
@@ -24,6 +25,28 @@ class DesktopTradeHistory extends ConsumerStatefulWidget {
 }
 
 class _DesktopTradeHistoryState extends ConsumerState<DesktopTradeHistory> {
+  BorderRadius get _borderRadiusFirst {
+    return BorderRadius.only(
+      topLeft: Radius.circular(
+        Constants.size.circularBorderRadius,
+      ),
+      topRight: Radius.circular(
+        Constants.size.circularBorderRadius,
+      ),
+    );
+  }
+
+  BorderRadius get _borderRadiusLast {
+    return BorderRadius.only(
+      bottomLeft: Radius.circular(
+        Constants.size.circularBorderRadius,
+      ),
+      bottomRight: Radius.circular(
+        Constants.size.circularBorderRadius,
+      ),
+    );
+  }
+
   @override
   Widget build(BuildContext context) {
     final trades =
@@ -33,169 +56,206 @@ class _DesktopTradeHistoryState extends ConsumerState<DesktopTradeHistory> {
     final hasHistory = tradeCount > 0;
 
     if (hasHistory) {
-      return ListView.separated(
-        shrinkWrap: true,
-        primary: false,
-        itemBuilder: (context, index) {
-          return TradeCard(
-            key: Key("tradeCard_${trades[index].uuid}"),
-            trade: trades[index],
-            onTap: () async {
-              final String tradeId = trades[index].tradeId;
-
-              final lookup = ref.read(tradeSentFromStackLookupProvider).all;
-
-              debugPrint("ALL: $lookup");
-
-              final String? txid = ref
-                  .read(tradeSentFromStackLookupProvider)
-                  .getTxidForTradeId(tradeId);
-              final List<String>? walletIds = ref
-                  .read(tradeSentFromStackLookupProvider)
-                  .getWalletIdsForTradeId(tradeId);
-
-              if (txid != null && walletIds != null && walletIds.isNotEmpty) {
-                final manager = ref
-                    .read(walletsChangeNotifierProvider)
-                    .getManager(walletIds.first);
-
-                debugPrint("name: ${manager.walletName}");
-
-                // TODO store tx data completely locally in isar so we don't lock up ui here when querying txData
-                final txData = await manager.transactionData;
-
-                final tx = txData.getAllTransactions()[txid];
-
-                if (mounted) {
-                  await showDialog<void>(
-                    context: context,
-                    builder: (context) => Navigator(
-                      initialRoute: TradeDetailsView.routeName,
-                      onGenerateRoute: RouteGenerator.generateRoute,
-                      onGenerateInitialRoutes: (_, __) {
-                        return [
-                          FadePageRoute(
-                            DesktopDialog(
-                              // maxHeight:
-                              //     MediaQuery.of(context).size.height - 64,
-                              maxHeight: double.infinity,
-                              maxWidth: 580,
-                              child: Column(
-                                mainAxisSize: MainAxisSize.min,
-                                children: [
-                                  Padding(
-                                    padding: const EdgeInsets.only(
-                                      left: 32,
-                                      bottom: 16,
-                                    ),
-                                    child: Row(
-                                      mainAxisAlignment:
-                                          MainAxisAlignment.spaceBetween,
-                                      children: [
-                                        Text(
-                                          "Trade details",
-                                          style: STextStyles.desktopH3(context),
-                                        ),
-                                        DesktopDialogCloseButton(
-                                          onPressedOverride: Navigator.of(
-                                            context,
-                                            rootNavigator: true,
-                                          ).pop,
-                                        ),
-                                      ],
-                                    ),
-                                  ),
-                                  Flexible(
-                                    child: TradeDetailsView(
-                                      tradeId: tradeId,
-                                      transactionIfSentFromStack: tx,
-                                      walletName: manager.walletName,
-                                      walletId: walletIds.first,
-                                    ),
-                                  ),
-                                ],
-                              ),
-                            ),
-                            const RouteSettings(
-                              name: TradeDetailsView.routeName,
-                            ),
-                          ),
-                        ];
-                      },
-                    ),
-                  );
+      return Column(
+        mainAxisSize: MainAxisSize.min,
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Text(
+            "Exchange details",
+            style: STextStyles.desktopTextExtraExtraSmall(context),
+          ),
+          const SizedBox(
+            height: 16,
+          ),
+          Expanded(
+            child: ListView.separated(
+              shrinkWrap: true,
+              primary: false,
+              itemBuilder: (context, index) {
+                BorderRadius? radius;
+                if (index == tradeCount - 1) {
+                  radius = _borderRadiusLast;
+                } else if (index == 0) {
+                  radius = _borderRadiusFirst;
                 }
-              } else {
-                unawaited(
-                  showDialog<void>(
-                    context: context,
-                    builder: (context) => Navigator(
-                      initialRoute: TradeDetailsView.routeName,
-                      onGenerateRoute: RouteGenerator.generateRoute,
-                      onGenerateInitialRoutes: (_, __) {
-                        return [
-                          FadePageRoute(
-                            DesktopDialog(
-                              // maxHeight:
-                              //     MediaQuery.of(context).size.height - 64,
-                              maxHeight: double.infinity,
-                              maxWidth: 580,
-                              child: Column(
-                                mainAxisSize: MainAxisSize.min,
-                                children: [
-                                  Padding(
-                                    padding: const EdgeInsets.only(
-                                      left: 32,
-                                      bottom: 16,
+
+                return Container(
+                  decoration: BoxDecoration(
+                    color: Theme.of(context).extension<StackColors>()!.popupBG,
+                    borderRadius: radius,
+                  ),
+                  child: TradeCard(
+                    key: Key("tradeCard_${trades[index].uuid}"),
+                    trade: trades[index],
+                    onTap: () async {
+                      final String tradeId = trades[index].tradeId;
+
+                      final lookup =
+                          ref.read(tradeSentFromStackLookupProvider).all;
+
+                      debugPrint("ALL: $lookup");
+
+                      final String? txid = ref
+                          .read(tradeSentFromStackLookupProvider)
+                          .getTxidForTradeId(tradeId);
+                      final List<String>? walletIds = ref
+                          .read(tradeSentFromStackLookupProvider)
+                          .getWalletIdsForTradeId(tradeId);
+
+                      if (txid != null &&
+                          walletIds != null &&
+                          walletIds.isNotEmpty) {
+                        final manager = ref
+                            .read(walletsChangeNotifierProvider)
+                            .getManager(walletIds.first);
+
+                        debugPrint("name: ${manager.walletName}");
+
+                        // TODO store tx data completely locally in isar so we don't lock up ui here when querying txData
+                        final txData = await manager.transactionData;
+
+                        final tx = txData.getAllTransactions()[txid];
+
+                        if (mounted) {
+                          await showDialog<void>(
+                            context: context,
+                            builder: (context) => Navigator(
+                              initialRoute: TradeDetailsView.routeName,
+                              onGenerateRoute: RouteGenerator.generateRoute,
+                              onGenerateInitialRoutes: (_, __) {
+                                return [
+                                  FadePageRoute(
+                                    DesktopDialog(
+                                      // maxHeight:
+                                      //     MediaQuery.of(context).size.height - 64,
+                                      maxHeight: double.infinity,
+                                      maxWidth: 580,
+                                      child: Column(
+                                        mainAxisSize: MainAxisSize.min,
+                                        children: [
+                                          Padding(
+                                            padding: const EdgeInsets.only(
+                                              left: 32,
+                                              bottom: 16,
+                                            ),
+                                            child: Row(
+                                              mainAxisAlignment:
+                                                  MainAxisAlignment
+                                                      .spaceBetween,
+                                              children: [
+                                                Text(
+                                                  "Trade details",
+                                                  style: STextStyles.desktopH3(
+                                                      context),
+                                                ),
+                                                DesktopDialogCloseButton(
+                                                  onPressedOverride:
+                                                      Navigator.of(
+                                                    context,
+                                                    rootNavigator: true,
+                                                  ).pop,
+                                                ),
+                                              ],
+                                            ),
+                                          ),
+                                          Flexible(
+                                            child: TradeDetailsView(
+                                              tradeId: tradeId,
+                                              transactionIfSentFromStack: tx,
+                                              walletName: manager.walletName,
+                                              walletId: walletIds.first,
+                                            ),
+                                          ),
+                                        ],
+                                      ),
                                     ),
-                                    child: Row(
-                                      mainAxisAlignment:
-                                          MainAxisAlignment.spaceBetween,
-                                      children: [
-                                        Text(
-                                          "Trade details",
-                                          style: STextStyles.desktopH3(context),
-                                        ),
-                                        DesktopDialogCloseButton(
-                                          onPressedOverride: Navigator.of(
-                                            context,
-                                            rootNavigator: true,
-                                          ).pop,
-                                        ),
-                                      ],
+                                    const RouteSettings(
+                                      name: TradeDetailsView.routeName,
                                     ),
                                   ),
-                                  Flexible(
-                                    child: TradeDetailsView(
-                                      tradeId: tradeId,
-                                      transactionIfSentFromStack: null,
-                                      walletName: null,
-                                      walletId: walletIds?.first,
-                                    ),
-                                  ),
-                                ],
-                              ),
+                                ];
+                              },
                             ),
-                            const RouteSettings(
-                              name: TradeDetailsView.routeName,
+                          );
+                        }
+                      } else {
+                        unawaited(
+                          showDialog<void>(
+                            context: context,
+                            builder: (context) => Navigator(
+                              initialRoute: TradeDetailsView.routeName,
+                              onGenerateRoute: RouteGenerator.generateRoute,
+                              onGenerateInitialRoutes: (_, __) {
+                                return [
+                                  FadePageRoute(
+                                    DesktopDialog(
+                                      // maxHeight:
+                                      //     MediaQuery.of(context).size.height - 64,
+                                      maxHeight: double.infinity,
+                                      maxWidth: 580,
+                                      child: Column(
+                                        mainAxisSize: MainAxisSize.min,
+                                        children: [
+                                          Padding(
+                                            padding: const EdgeInsets.only(
+                                              left: 32,
+                                              bottom: 16,
+                                            ),
+                                            child: Row(
+                                              mainAxisAlignment:
+                                                  MainAxisAlignment
+                                                      .spaceBetween,
+                                              children: [
+                                                Text(
+                                                  "Trade details",
+                                                  style: STextStyles.desktopH3(
+                                                      context),
+                                                ),
+                                                DesktopDialogCloseButton(
+                                                  onPressedOverride:
+                                                      Navigator.of(
+                                                    context,
+                                                    rootNavigator: true,
+                                                  ).pop,
+                                                ),
+                                              ],
+                                            ),
+                                          ),
+                                          Flexible(
+                                            child: TradeDetailsView(
+                                              tradeId: tradeId,
+                                              transactionIfSentFromStack: null,
+                                              walletName: null,
+                                              walletId: walletIds?.first,
+                                            ),
+                                          ),
+                                        ],
+                                      ),
+                                    ),
+                                    const RouteSettings(
+                                      name: TradeDetailsView.routeName,
+                                    ),
+                                  ),
+                                ];
+                              },
                             ),
                           ),
-                        ];
-                      },
-                    ),
+                        );
+                      }
+                    },
                   ),
                 );
-              }
-            },
-          );
-        },
-        separatorBuilder: (context, index) {
-          return Container(
-            height: 1,
-            color: Theme.of(context).extension<StackColors>()!.background,
-          );
-        },
-        itemCount: tradeCount,
+              },
+              separatorBuilder: (context, index) {
+                return Container(
+                  height: 1,
+                  color: Theme.of(context).extension<StackColors>()!.background,
+                );
+              },
+              itemCount: tradeCount,
+            ),
+          ),
+        ],
       );
     } else {
       return RoundedWhiteContainer(

From 4debb0fff9d67087f20743c4c3899996085c6b41 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 16:34:31 -0600
Subject: [PATCH 099/100] desktop block explorer warning dialog navigation fix

---
 .../transaction_views/transaction_details_view.dart    | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart
index dc4e41152..4d45428ff 100644
--- a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart
+++ b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart
@@ -266,7 +266,10 @@ class _TransactionDetailsViewState
                           buttonHeight: ButtonHeight.l,
                           label: "Cancel",
                           onPressed: () {
-                            Navigator.of(context).pop(false);
+                            Navigator.of(
+                              context,
+                              rootNavigator: true,
+                            ).pop(false);
                           },
                         ),
                         const SizedBox(width: 20),
@@ -275,7 +278,10 @@ class _TransactionDetailsViewState
                           buttonHeight: ButtonHeight.l,
                           label: "Continue",
                           onPressed: () {
-                            Navigator.of(context).pop(true);
+                            Navigator.of(
+                              context,
+                              rootNavigator: true,
+                            ).pop(true);
                           },
                         ),
                       ],

From 67d375dbd5ba0b994fa9d370dd6787e197a6dbf5 Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Tue, 22 Nov 2022 16:37:47 -0600
Subject: [PATCH 100/100] desktop new notifications bell icon indicator

---
 .../home/desktop_menu.dart                    | 32 ++++++++++++-------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/lib/pages_desktop_specific/home/desktop_menu.dart b/lib/pages_desktop_specific/home/desktop_menu.dart
index 60a424a06..d82d62883 100644
--- a/lib/pages_desktop_specific/home/desktop_menu.dart
+++ b/lib/pages_desktop_specific/home/desktop_menu.dart
@@ -5,6 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_svg/flutter_svg.dart';
 import 'package:stackwallet/pages_desktop_specific/home/desktop_menu_item.dart';
 import 'package:stackwallet/providers/desktop/current_desktop_menu_item.dart';
+import 'package:stackwallet/providers/providers.dart';
 import 'package:stackwallet/utilities/assets.dart';
 import 'package:stackwallet/utilities/text_styles.dart';
 import 'package:stackwallet/utilities/theme/stack_colors.dart';
@@ -149,20 +150,27 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
                     ),
                     DesktopMenuItem(
                       icon: SvgPicture.asset(
-                        Assets.svg.bell,
+                        ref.watch(notificationsProvider.select(
+                                (value) => value.hasUnreadNotifications))
+                            ? Assets.svg.bellNew(context)
+                            : Assets.svg.bell,
                         width: 20,
                         height: 20,
-                        color: DesktopMenuItemId.notifications ==
-                                ref
-                                    .watch(currentDesktopMenuItemProvider.state)
-                                    .state
-                            ? Theme.of(context)
-                                .extension<StackColors>()!
-                                .accentColorDark
-                            : Theme.of(context)
-                                .extension<StackColors>()!
-                                .accentColorDark
-                                .withOpacity(0.8),
+                        color: ref.watch(notificationsProvider.select(
+                                (value) => value.hasUnreadNotifications))
+                            ? null
+                            : DesktopMenuItemId.notifications ==
+                                    ref
+                                        .watch(currentDesktopMenuItemProvider
+                                            .state)
+                                        .state
+                                ? Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .accentColorDark
+                                : Theme.of(context)
+                                    .extension<StackColors>()!
+                                    .accentColorDark
+                                    .withOpacity(0.8),
                       ),
                       label: "Notifications",
                       value: DesktopMenuItemId.notifications,