From 890e95e5ad91d10ffc501515a29758a9ea0afcb5 Mon Sep 17 00:00:00 2001 From: MinhDV Date: Thu, 28 Sep 2023 11:10:11 +0700 Subject: [PATCH] fix: Highlight keyword when search contacts --- .../contacts_tab/contacts_tab_body_view.dart | 6 +- .../widget/contacts_selection_list.dart | 63 +++++++++++++------ .../widget/contacts_selection_list_style.dart | 6 ++ .../widget/expansion_contact_list_tile.dart | 14 +++-- .../widget/expansion_list.dart | 5 +- lib/pages/search/recent_item_widget.dart | 36 +++++++++-- lib/utils/display_name_widget.dart | 25 +++----- lib/widgets/highlight_text.dart | 12 +++- 8 files changed, 115 insertions(+), 52 deletions(-) create mode 100644 lib/pages/new_group/widget/contacts_selection_list_style.dart diff --git a/lib/pages/contacts_tab/contacts_tab_body_view.dart b/lib/pages/contacts_tab/contacts_tab_body_view.dart index 67ea11c4ec..fe0461c7cf 100644 --- a/lib/pages/contacts_tab/contacts_tab_body_view.dart +++ b/lib/pages/contacts_tab/contacts_tab_body_view.dart @@ -59,8 +59,10 @@ class ContactsTabBodyView extends StatelessWidget { contact: contact, ); }, - child: - ExpansionContactListTile(contact: contact), + child: ExpansionContactListTile( + contact: contact, + highlightKeyword: success.keyword, + ), ), ) .toList() diff --git a/lib/pages/new_group/widget/contacts_selection_list.dart b/lib/pages/new_group/widget/contacts_selection_list.dart index f78cda50cb..a243784fe8 100644 --- a/lib/pages/new_group/widget/contacts_selection_list.dart +++ b/lib/pages/new_group/widget/contacts_selection_list.dart @@ -1,6 +1,7 @@ import 'package:dartz/dartz.dart'; import 'package:fluffychat/app_state/failure.dart'; import 'package:fluffychat/app_state/success.dart'; +import 'package:fluffychat/pages/new_group/widget/contacts_selection_list_style.dart'; import 'package:fluffychat/presentation/model/presentation_contact.dart'; import 'package:flutter/material.dart'; @@ -31,17 +32,18 @@ class ContactsSelectionList extends StatelessWidget { valueListenable: contactsNotifier, builder: (context, value, child) => value.fold( (failure) => Padding( - padding: const EdgeInsets.only(left: 8.0), + padding: ContactsSelectionListStyle.notFoundPadding, child: NoContactsFound( keyword: failure is GetContactsFailure ? failure.keyword : '', ), ), (success) { if (success is PresentationExternalContactSuccess) { - return _buildContactItem( - context, + return _ContactItem( + selectedContactsMapNotifier: selectedContactsMapNotifier, + onSelectedContact: onSelectedContact, contact: success.contact, - paddingTop: 8, + paddingTop: ContactsSelectionListStyle.listPaddingTop, ); } if (success is! PresentationContactsSuccess) { @@ -50,7 +52,7 @@ class ContactsSelectionList extends StatelessWidget { if (success.keyword.isNotEmpty && success.data.isEmpty) { return Padding( - padding: const EdgeInsets.only(left: 8.0), + padding: ContactsSelectionListStyle.notFoundPadding, child: NoContactsFound( keyword: success.keyword, ), @@ -61,27 +63,49 @@ class ContactsSelectionList extends StatelessWidget { shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: success.data.length, - itemBuilder: (context, index) => _buildContactItem( - context, - contact: success.data[index], - paddingTop: index == 0 ? 8.0 : 0, - ), + itemBuilder: (context, index) { + final contact = success.data[index]; + final disabled = disabledContactIds.contains( + contact.matrixId, + ); + return _ContactItem( + contact: contact, + selectedContactsMapNotifier: selectedContactsMapNotifier, + onSelectedContact: onSelectedContact, + highlightKeyword: success.keyword, + disabled: disabled, + paddingTop: + index == 0 ? ContactsSelectionListStyle.listPaddingTop : 0, + ); + }, ); }, ), ); } +} + +class _ContactItem extends StatelessWidget { + final PresentationContact contact; + final SelectedContactsMapChangeNotifier selectedContactsMapNotifier; + final VoidCallback? onSelectedContact; + final bool disabled; + final double paddingTop; + final String highlightKeyword; - Widget _buildContactItem( - BuildContext context, { - required PresentationContact contact, - double paddingTop = 0, - }) { + 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); - final disabled = disabledContactIds.contains( - contact.matrixId, - ); return InkWell( key: ValueKey(contact.matrixId), onTap: disabled @@ -115,7 +139,7 @@ class ContactsSelectionList extends StatelessWidget { context, contact, ); - onSelectedContact(); + onSelectedContact?.call(); }, ); }, @@ -123,6 +147,7 @@ class ContactsSelectionList extends StatelessWidget { 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 new file mode 100644 index 0000000000..107b5625d4 --- /dev/null +++ b/lib/pages/new_group/widget/contacts_selection_list_style.dart @@ -0,0 +1,6 @@ +import 'package:flutter/widgets.dart'; + +class ContactsSelectionListStyle { + static const notFoundPadding = EdgeInsetsDirectional.only(start: 8.0); + static const listPaddingTop = 8.0; +} diff --git a/lib/pages/new_private_chat/widget/expansion_contact_list_tile.dart b/lib/pages/new_private_chat/widget/expansion_contact_list_tile.dart index 454cdef00a..a4a97b9497 100644 --- a/lib/pages/new_private_chat/widget/expansion_contact_list_tile.dart +++ b/lib/pages/new_private_chat/widget/expansion_contact_list_tile.dart @@ -3,6 +3,7 @@ import 'package:fluffychat/presentation/model/presentation_contact.dart'; import 'package:fluffychat/pages/new_private_chat/widget/contact_status_widget.dart'; import 'package:fluffychat/utils/display_name_widget.dart'; import 'package:fluffychat/widgets/avatar/avatar.dart'; +import 'package:fluffychat/widgets/highlight_text.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/twake_components/twake_chip.dart'; import 'package:flutter/material.dart'; @@ -15,10 +16,12 @@ typedef OnExpansionListTileTap = void Function(); class ExpansionContactListTile extends StatelessWidget { final PresentationContact contact; + final String highlightKeyword; const ExpansionContactListTile({ super.key, required this.contact, + this.highlightKeyword = '', }); @override @@ -58,6 +61,7 @@ class ExpansionContactListTile extends StatelessWidget { profileDisplayName: snapshot.data?.displayName, contactDisplayName: contact.displayName, + highlightKeyword: highlightKeyword, style: Theme.of(context) .textTheme .titleMedium @@ -88,15 +92,17 @@ class ExpansionContactListTile extends StatelessWidget { ), ), if (contact.matrixId != null) - Text( - contact.matrixId!, + HighlightText( + text: contact.matrixId!, + searchWord: highlightKeyword, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: LinagoraRefColors.material().neutral[60], ), ), if (contact.email != null) - Text( - contact.email!, + HighlightText( + text: contact.email!, + searchWord: highlightKeyword, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: LinagoraRefColors.material().neutral[60], ), diff --git a/lib/pages/new_private_chat/widget/expansion_list.dart b/lib/pages/new_private_chat/widget/expansion_list.dart index 57ce11954d..e17c3415f9 100644 --- a/lib/pages/new_private_chat/widget/expansion_list.dart +++ b/lib/pages/new_private_chat/widget/expansion_list.dart @@ -134,7 +134,10 @@ class ExpansionList extends StatelessWidget { ); }, borderRadius: BorderRadius.circular(16.0), - child: ExpansionContactListTile(contact: contact), + child: ExpansionContactListTile( + contact: contact, + highlightKeyword: success.keyword, + ), ); }, ); diff --git a/lib/pages/search/recent_item_widget.dart b/lib/pages/search/recent_item_widget.dart index db063ace19..b7aea1ba9a 100644 --- a/lib/pages/search/recent_item_widget.dart +++ b/lib/pages/search/recent_item_widget.dart @@ -98,7 +98,7 @@ class _GroupChatInformation extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - HighlightText( + _SearchHighlightText( text: recentChatPresentationSearch.displayName ?? "", style: Theme.of(context).textTheme.titleMedium?.merge( TextStyle( @@ -130,6 +130,30 @@ class _GroupChatInformation extends StatelessWidget { } } +class _SearchHighlightText extends StatelessWidget { + final String text; + final String? searchWord; + final TextStyle? style; + + const _SearchHighlightText({ + required this.text, + this.searchWord, + this.style, + }); + + @override + Widget build(BuildContext context) { + return HighlightText( + text: text, + style: style, + searchWord: searchWord, + maxLines: 1, + overflow: TextOverflow.ellipsis, + softWrap: false, + ); + } +} + class _DirectChatInformation extends StatelessWidget { final RecentChatPresentationSearch recentChatPresentationSearch; final String? searchKeyword; @@ -155,7 +179,7 @@ class _DirectChatInformation extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - HighlightText( + _SearchHighlightText( text: recentChatPresentationSearch.displayName ?? "", style: Theme.of(context).textTheme.titleMedium?.merge( TextStyle( @@ -166,7 +190,7 @@ class _DirectChatInformation extends StatelessWidget { ), searchWord: searchKeyword, ), - HighlightText( + _SearchHighlightText( text: recentChatPresentationSearch.directChatMatrixID ?? "", style: Theme.of(context).textTheme.bodyMedium?.merge( TextStyle( @@ -217,7 +241,7 @@ class _ContactInformation extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - HighlightText( + _SearchHighlightText( text: contactPresentationSearch.displayName ?? "", style: Theme.of(context).textTheme.titleMedium?.merge( TextStyle( @@ -232,7 +256,7 @@ class _ContactInformation extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ if (contactPresentationSearch.matrixId != null) - HighlightText( + _SearchHighlightText( text: contactPresentationSearch.matrixId ?? "", style: Theme.of(context).textTheme.bodyMedium?.merge( TextStyle( @@ -244,7 +268,7 @@ class _ContactInformation extends StatelessWidget { searchWord: searchKeyword, ), if (contactPresentationSearch.email != null) - HighlightText( + _SearchHighlightText( text: contactPresentationSearch.email ?? "", style: Theme.of(context).textTheme.bodyMedium?.merge( TextStyle( diff --git a/lib/utils/display_name_widget.dart b/lib/utils/display_name_widget.dart index cad1daa823..8cc1addaf6 100644 --- a/lib/utils/display_name_widget.dart +++ b/lib/utils/display_name_widget.dart @@ -1,37 +1,28 @@ +import 'package:fluffychat/widgets/highlight_text.dart'; import 'package:flutter/material.dart'; class BuildDisplayName extends StatelessWidget { final String? profileDisplayName; final String? contactDisplayName; + final String highlightKeyword; final TextStyle? style; const BuildDisplayName({ super.key, this.profileDisplayName, this.contactDisplayName, + this.highlightKeyword = "", this.style, }); @override Widget build(BuildContext context) { - if (profileDisplayName != null) { - return _DisplayName(displayName: profileDisplayName!, style: style); - } else if (contactDisplayName != null) { - return _DisplayName(displayName: contactDisplayName!, style: style); - } else { + final displayName = profileDisplayName ?? contactDisplayName; + if (displayName == null) { return const SizedBox.shrink(); } - } -} - -class _DisplayName extends StatelessWidget { - final String displayName; - final TextStyle? style; - const _DisplayName({required this.displayName, this.style}); - - @override - Widget build(BuildContext context) { - return Text( - displayName, + return HighlightText( + text: displayName, + searchWord: highlightKeyword, style: style ?? Theme.of(context).textTheme.bodySmall!.copyWith( color: Theme.of(context).colorScheme.onSurface, diff --git a/lib/widgets/highlight_text.dart b/lib/widgets/highlight_text.dart index 0d2bb3aa6e..c24905e8ea 100644 --- a/lib/widgets/highlight_text.dart +++ b/lib/widgets/highlight_text.dart @@ -6,6 +6,9 @@ class HighlightText extends StatelessWidget { final String? searchWord; final TextStyle? style; final TextStyle? highlightStyle; + final int? maxLines; + final TextOverflow? overflow; + final bool? softWrap; const HighlightText({ super.key, @@ -13,6 +16,9 @@ class HighlightText extends StatelessWidget { required this.searchWord, required this.style, this.highlightStyle, + this.maxLines, + this.overflow, + this.softWrap, }); @override @@ -28,9 +34,9 @@ class HighlightText extends StatelessWidget { ); return Text.rich( TextSpan(children: spans), - maxLines: 1, - overflow: TextOverflow.ellipsis, - softWrap: false, + maxLines: maxLines, + overflow: overflow, + softWrap: softWrap, ); } }