From 35bfa150c31096abeb24b5e081f940d352b7c25a Mon Sep 17 00:00:00 2001 From: HuyNguyen Date: Mon, 20 May 2024 17:14:22 +0700 Subject: [PATCH] TW-1772: Showing no contact in new group chat screen --- .../new_group/contacts_selection_view.dart | 37 ++++++ lib/pages/new_group/widget/contact_item.dart | 79 ++++++++++++ .../widget/contacts_selection_list.dart | 114 ++++++------------ .../widget/contacts_selection_list_style.dart | 6 +- .../contacts_view_controller_mixin.dart | 6 - 5 files changed, 155 insertions(+), 87 deletions(-) create mode 100644 lib/pages/new_group/widget/contact_item.dart diff --git a/lib/pages/new_group/contacts_selection_view.dart b/lib/pages/new_group/contacts_selection_view.dart index 98bb611816..161cc74529 100644 --- a/lib/pages/new_group/contacts_selection_view.dart +++ b/lib/pages/new_group/contacts_selection_view.dart @@ -1,9 +1,12 @@ import 'package:fluffychat/pages/new_group/contacts_selection.dart'; import 'package:fluffychat/pages/new_group/contacts_selection_view_style.dart'; +import 'package:fluffychat/pages/new_group/widget/contact_item.dart'; import 'package:fluffychat/pages/new_group/widget/contacts_selection_list.dart'; import 'package:fluffychat/pages/new_group/widget/selected_participants_list.dart'; +import 'package:fluffychat/presentation/model/search/presentation_search.dart'; import 'package:fluffychat/widgets/app_bars/searchable_app_bar.dart'; import 'package:fluffychat/widgets/contacts_warning_banner/contacts_warning_banner_view.dart'; +import 'package:fluffychat/widgets/sliver_expandable_list.dart'; import 'package:fluffychat/widgets/twake_components/twake_fab.dart'; import 'package:fluffychat/widgets/twake_components/twake_text_button.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -61,9 +64,43 @@ class ContactsSelectionView extends StatelessWidget { contactsSelectionController: controller, ), ), + ValueListenableBuilder( + valueListenable: + controller.presentationRecentContactNotifier, + builder: (context, recentContacts, child) { + if (recentContacts.isEmpty) { + return child!; + } + return SliverExpandableList( + title: L10n.of(context)!.recentChat, + itemCount: recentContacts.length, + itemBuilder: (context, index) { + final disabled = + controller.disabledContactIds.contains( + recentContacts[index].directChatMatrixID, + ); + return ContactItem( + contact: + recentContacts[index].toPresentationContact(), + selectedContactsMapNotifier: + controller.selectedContactsMapNotifier, + onSelectedContact: controller.onSelectedContact, + highlightKeyword: + controller.textEditingController.text, + disabled: disabled, + ); + }, + ); + }, + child: const SliverToBoxAdapter( + child: SizedBox(), + ), + ), ContactsSelectionList( presentationContactNotifier: controller.presentationContactNotifier, + presentationRecentContactNotifier: + controller.presentationRecentContactNotifier, selectedContactsMapNotifier: controller.selectedContactsMapNotifier, onSelectedContact: controller.onSelectedContact, diff --git a/lib/pages/new_group/widget/contact_item.dart b/lib/pages/new_group/widget/contact_item.dart new file mode 100644 index 0000000000..7e8112b017 --- /dev/null +++ b/lib/pages/new_group/widget/contact_item.dart @@ -0,0 +1,79 @@ +import 'package:fluffychat/pages/new_group/selected_contacts_map_change_notifier.dart'; +import 'package:fluffychat/pages/new_group/widget/contacts_selection_list_style.dart'; +import 'package:fluffychat/pages/new_private_chat/widget/expansion_contact_list_tile.dart'; +import 'package:fluffychat/presentation/model/contact/presentation_contact.dart'; +import 'package:flutter/material.dart'; + +class ContactItem extends StatelessWidget { + final PresentationContact contact; + final SelectedContactsMapChangeNotifier selectedContactsMapNotifier; + final VoidCallback? onSelectedContact; + final bool disabled; + final double paddingTop; + final String highlightKeyword; + + const ContactItem({ + super.key, + required this.contact, + required this.selectedContactsMapNotifier, + this.onSelectedContact, + this.highlightKeyword = '', + this.disabled = false, + this.paddingTop = 0, + }); + + @override + Widget build(BuildContext context) { + final contactNotifier = + selectedContactsMapNotifier.getNotifierAtContact(contact); + return Padding( + padding: ContactsSelectionListStyle.contactItemPadding, + child: InkWell( + key: ValueKey(contact.matrixId), + onTap: disabled + ? null + : () { + onSelectedContact?.call(); + selectedContactsMapNotifier.onContactTileTap( + context, + contact, + ); + }, + borderRadius: ContactsSelectionListStyle.contactItemBorderRadius, + child: SizedBox( + width: MediaQuery.of(context).size.width, + child: Padding( + padding: ContactsSelectionListStyle.checkBoxPadding(paddingTop), + child: Row( + children: [ + ValueListenableBuilder( + valueListenable: contactNotifier, + builder: (context, isCurrentSelected, child) { + return Checkbox( + value: disabled || contactNotifier.value, + onChanged: disabled + ? null + : (newValue) { + onSelectedContact?.call(); + selectedContactsMapNotifier.onContactTileTap( + context, + contact, + ); + }, + ); + }, + ), + Expanded( + child: ExpansionContactListTile( + contact: contact, + highlightKeyword: highlightKeyword, + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/new_group/widget/contacts_selection_list.dart b/lib/pages/new_group/widget/contacts_selection_list.dart index 812370a40f..e524391397 100644 --- a/lib/pages/new_group/widget/contacts_selection_list.dart +++ b/lib/pages/new_group/widget/contacts_selection_list.dart @@ -2,18 +2,23 @@ import 'package:dartz/dartz.dart'; import 'package:fluffychat/app_state/failure.dart'; import 'package:fluffychat/app_state/success.dart'; import 'package:fluffychat/domain/app_state/contact/get_contacts_state.dart'; +import 'package:fluffychat/pages/new_group/widget/contact_item.dart'; import 'package:fluffychat/pages/new_group/widget/contacts_selection_list_style.dart'; import 'package:fluffychat/pages/new_private_chat/widget/loading_contact_widget.dart'; -import 'package:fluffychat/presentation/model/contact/presentation_contact.dart'; +import 'package:fluffychat/presentation/model/contact/get_presentation_contacts_empty.dart'; +import 'package:fluffychat/presentation/model/contact/get_presentation_contacts_failure.dart'; import 'package:fluffychat/presentation/model/contact/presentation_contact_success.dart'; +import 'package:fluffychat/presentation/model/search/presentation_search.dart'; +import 'package:fluffychat/widgets/sliver_expandable_list.dart'; import 'package:flutter/material.dart'; - +import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:fluffychat/pages/new_group/selected_contacts_map_change_notifier.dart'; -import 'package:fluffychat/pages/new_private_chat/widget/expansion_contact_list_tile.dart'; import 'package:fluffychat/pages/new_private_chat/widget/no_contacts_found.dart'; class ContactsSelectionList extends StatelessWidget { final SelectedContactsMapChangeNotifier selectedContactsMapNotifier; + final ValueNotifier> + presentationRecentContactNotifier; final ValueNotifier> presentationContactNotifier; final Function() onSelectedContact; final List disabledContactIds; @@ -26,6 +31,7 @@ class ContactsSelectionList extends StatelessWidget { required this.onSelectedContact, this.disabledContactIds = const [], required this.textEditingController, + required this.presentationRecentContactNotifier, }) : super(key: key); @override @@ -36,7 +42,27 @@ class ContactsSelectionList extends StatelessWidget { final isSearchModeEnable = textEditingController.text.isNotEmpty; return state.fold( - (_) => child!, + (failure) { + final recentContact = + presentationRecentContactNotifier.value.isEmpty; + final textControllerIsEmpty = textEditingController.text.isEmpty; + if (failure is GetPresentationContactsEmpty || + failure is GetPresentationContactsFailure) { + if (recentContact) { + return SliverToBoxAdapter( + child: Padding( + padding: ContactsSelectionListStyle.notFoundPadding, + child: NoContactsFound( + keyword: textControllerIsEmpty + ? null + : textEditingController.text, + ), + ), + ); + } + } + return child!; + }, (success) { if (success is ContactsLoading) { return const SliverToBoxAdapter( @@ -46,7 +72,7 @@ class ContactsSelectionList extends StatelessWidget { if (success is PresentationExternalContactSuccess) { return SliverToBoxAdapter( - child: _ContactItem( + child: ContactItem( contact: success.contact, selectedContactsMapNotifier: selectedContactsMapNotifier, onSelectedContact: onSelectedContact, @@ -68,13 +94,14 @@ class ContactsSelectionList extends StatelessWidget { ), ); } - return SliverList.builder( + return SliverExpandableList( + title: L10n.of(context)!.linagoraContactsCount(contacts.length), itemCount: contacts.length, itemBuilder: (context, index) { final disabled = disabledContactIds.contains( contacts[index].matrixId, ); - return _ContactItem( + return ContactItem( contact: contacts[index], selectedContactsMapNotifier: selectedContactsMapNotifier, onSelectedContact: onSelectedContact, @@ -95,76 +122,3 @@ class ContactsSelectionList extends StatelessWidget { ); } } - -class _ContactItem extends StatelessWidget { - final PresentationContact contact; - final SelectedContactsMapChangeNotifier selectedContactsMapNotifier; - final VoidCallback? onSelectedContact; - final bool disabled; - final double paddingTop; - final String highlightKeyword; - - const _ContactItem({ - required this.contact, - required this.selectedContactsMapNotifier, - this.onSelectedContact, - this.highlightKeyword = '', - this.disabled = false, - this.paddingTop = 0, - }); - - @override - Widget build(BuildContext context) { - final contactNotifier = - selectedContactsMapNotifier.getNotifierAtContact(contact); - return Padding( - padding: ContactsSelectionListStyle.contactItemPadding, - child: InkWell( - key: ValueKey(contact.matrixId), - onTap: disabled - ? null - : () { - onSelectedContact?.call(); - selectedContactsMapNotifier.onContactTileTap( - context, - contact, - ); - }, - borderRadius: ContactsSelectionListStyle.contactItemBorderRadius, - child: SizedBox( - width: MediaQuery.of(context).size.width, - child: Padding( - padding: ContactsSelectionListStyle.checkBoxPadding(paddingTop), - child: Row( - children: [ - ValueListenableBuilder( - valueListenable: contactNotifier, - builder: (context, isCurrentSelected, child) { - return Checkbox( - value: disabled || contactNotifier.value, - onChanged: disabled - ? null - : (newValue) { - onSelectedContact?.call(); - selectedContactsMapNotifier.onContactTileTap( - context, - contact, - ); - }, - ); - }, - ), - Expanded( - child: ExpansionContactListTile( - contact: contact, - highlightKeyword: highlightKeyword, - ), - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/pages/new_group/widget/contacts_selection_list_style.dart b/lib/pages/new_group/widget/contacts_selection_list_style.dart index c8b27596e2..431716c448 100644 --- a/lib/pages/new_group/widget/contacts_selection_list_style.dart +++ b/lib/pages/new_group/widget/contacts_selection_list_style.dart @@ -1,7 +1,11 @@ import 'package:flutter/widgets.dart'; class ContactsSelectionListStyle { - static const notFoundPadding = EdgeInsetsDirectional.only(top: 12.0); + static const notFoundPadding = EdgeInsetsDirectional.only( + top: 12.0, + start: 16.0, + end: 16.0, + ); static const listPaddingTop = 8.0; static BorderRadius contactItemBorderRadius = BorderRadius.circular(16.0); diff --git a/lib/presentation/mixins/contacts_view_controller_mixin.dart b/lib/presentation/mixins/contacts_view_controller_mixin.dart index 216f76ac85..567e3278ed 100644 --- a/lib/presentation/mixins/contacts_view_controller_mixin.dart +++ b/lib/presentation/mixins/contacts_view_controller_mixin.dart @@ -313,11 +313,5 @@ mixin class ContactsViewControllerMixin { textEditingController.dispose(); presentationContactNotifier.dispose(); presentationPhonebookContactNotifier.dispose(); - contactsManager - .getContactsNotifier() - .removeListener(() => _refreshAllContacts); - contactsManager - .getPhonebookContactsNotifier() - .removeListener(() => _refreshAllContacts); } }