From e0555f53a437d37e8c5c951de2c9c7f90448b7eb Mon Sep 17 00:00:00 2001 From: ryleedavis Date: Mon, 14 Nov 2022 16:00:09 -0700 Subject: [PATCH] WIP: desktop address book displays contacts --- .../address_book_views/address_book_view.dart | 553 +++++++++--------- .../desktop_address_book.dart | 31 +- 2 files changed, 288 insertions(+), 296 deletions(-) diff --git a/lib/pages/address_book_views/address_book_view.dart b/lib/pages/address_book_views/address_book_view.dart index c9dd72d72..08c548627 100644 --- a/lib/pages/address_book_views/address_book_view.dart +++ b/lib/pages/address_book_views/address_book_view.dart @@ -13,7 +13,9 @@ 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/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'; @@ -21,8 +23,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 AddressBookView extends ConsumerStatefulWidget { const AddressBookView({Key? key, this.coin}) : super(key: key); @@ -103,288 +103,287 @@ class _AddressBookViewState extends ConsumerState { final addressBookEntriesFuture = ref.watch( addressBookServiceProvider.select((value) => value.addressBookEntries)); - return Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Address book", - style: STextStyles.navBarTitle(context), - ), - actions: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, + final isDesktop = Util.isDesktop; + return ConditionalParent( + condition: !isDesktop, + builder: (child) { + return Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("addressBookFilterViewButton"), - size: 36, - shadows: const [], - color: Theme.of(context).extension()!.background, - icon: SvgPicture.asset( - Assets.svg.filter, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 20, - height: 20, + title: Text( + "Address book", + style: STextStyles.navBarTitle(context), + ), + actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, ), - onPressed: () { - Navigator.of(context).pushNamed( - AddressBookFilterView.routeName, - ); - }, - ), - ), - ), - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("addressBookAddNewContactViewButton"), - size: 36, - shadows: const [], - color: Theme.of(context).extension()!.background, - icon: SvgPicture.asset( - Assets.svg.plus, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 20, - height: 20, - ), - onPressed: () { - Navigator.of(context).pushNamed( - AddAddressBookEntryView.routeName, - ); - }, - ), - ), - ), - ], - ), - 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: [ - 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: 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, - ), - ), - ), - const SizedBox( - height: 16, - ), - Text( - "Favorites", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), - FutureBuilder( - future: addressBookEntriesFuture, - builder: (_, AsyncSnapshot> 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: const EdgeInsets.all(0), - 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), - ), - ), - ); - } - } - }, - ), - const SizedBox( - height: 16, - ), - Text( - "All contacts", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), - FutureBuilder( - future: addressBookEntriesFuture, - builder: (_, AsyncSnapshot> 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 RoundedWhiteContainer( - padding: const EdgeInsets.all(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( - "contactCard_${e.id}_key"), - contactId: e.id, - ), - ), - ], - ), - ); - } else { - return RoundedWhiteContainer( - child: Center( - child: Text( - "Your contacts will appear here", - style: STextStyles.itemSubtitle(context), - ), - ), - ); - } - } - }, - ), - ], + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("addressBookFilterViewButton"), + size: 36, + shadows: const [], + color: + Theme.of(context).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.filter, + color: Theme.of(context) + .extension()! + .accentColorDark, + width: 20, + height: 20, ), + onPressed: () { + Navigator.of(context).pushNamed( + AddressBookFilterView.routeName, + ); + }, ), ), ), + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("addressBookAddNewContactViewButton"), + size: 36, + shadows: const [], + color: + Theme.of(context).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.plus, + color: Theme.of(context) + .extension()! + .accentColorDark, + width: 20, + height: 20, + ), + onPressed: () { + Navigator.of(context).pushNamed( + AddAddressBookEntryView.routeName, + ); + }, + ), + ), + ), + ], + ), + 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: 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, + ), + FutureBuilder( + future: addressBookEntriesFuture, + builder: (_, AsyncSnapshot> 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), + ), + ), + ); + } + } + }, + ), + const SizedBox( + height: 16, + ), + Text( + "All contacts", + style: STextStyles.smallMed12(context), + ), + const SizedBox( + height: 12, + ), + FutureBuilder( + future: addressBookEntriesFuture, + builder: (_, AsyncSnapshot> 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 RoundedWhiteContainer( + padding: EdgeInsets.all(!isDesktop ? 0 : 15), + 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, + ), + ), + ], + ), + ); + } else { + return 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 e375bbcc7..475650722 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 @@ -2,6 +2,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/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'; @@ -9,11 +10,11 @@ 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/desktop/desktop_app_bar.dart'; import 'package:stackwallet/widgets/desktop/desktop_dialog.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'; @@ -36,7 +37,7 @@ class _DesktopAddressBook extends ConsumerState { late bool hasContacts = false; - String filter = ""; + String _searchTerm = ""; Future selectCryptocurrency() async { await showDialog( @@ -123,25 +124,25 @@ class _DesktopAddressBook extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( - autocorrect: false, - enableSuggestions: false, + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _searchController, focusNode: _searchFocusNode, - onChanged: (newString) { - setState(() => filter = newString); + onChanged: (value) { + setState(() { + _searchTerm = value; + }); }, style: STextStyles.field(context), decoration: standardInputDecoration( - "Search...", + "Search", _searchFocusNode, context, ).copyWith( - labelStyle: STextStyles.fieldLabel(context) - .copyWith(fontSize: 16), prefixIcon: Padding( padding: const EdgeInsets.symmetric( horizontal: 10, - vertical: 16, + vertical: 20, ), child: SvgPicture.asset( Assets.svg.search, @@ -160,7 +161,6 @@ class _DesktopAddressBook extends ConsumerState { onTap: () async { setState(() { _searchController.text = ""; - filter = ""; }); }, ), @@ -243,14 +243,7 @@ class _DesktopAddressBook extends ConsumerState { padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 26), child: SizedBox( width: 489, - child: RoundedWhiteContainer( - child: Center( - child: Text( - "Your contacts will appear here", - style: STextStyles.itemSubtitle(context), - ), - ), - ), + child: AddressBookView(), ), ), ],