From 49103c86f1b63bd56563a0aa1167bcda5ee69cd8 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 17 Nov 2022 09:00:10 -0600 Subject: [PATCH] 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 { _searchController = TextEditingController(); _searchFocusNode = FocusNode(); + ref.refresh(addressBookFilterProvider); + + // if (widget.coin == null) { + List 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 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 { @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 { ), ), 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()! + .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()! + .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()! - .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()! - .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(), + ), + ], + ), + ), + ], + ), + ) + ], ); } }