From 0ff9bc3c4051e1caa3254d3f4ba96ab32665e5e5 Mon Sep 17 00:00:00 2001 From: HuyNguyen Date: Tue, 24 Dec 2024 00:00:30 +0700 Subject: [PATCH 1/5] TW-2165: Improve tag suggestion with members in room --- lib/pages/chat/chat.dart | 16 ++++++- .../chat_details_members_page.dart | 9 ++-- .../mixins/chat_details_tab_mixin.dart | 47 +++++++++++++++---- pubspec.yaml | 2 +- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index e4a8c83925..803bf11cbb 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -291,6 +291,19 @@ class ChatController extends State } } + Future _requestParticipants() async { + if (room == null) return; + try { + await room!.requestParticipants( + at: room!.prev_batch, + notMembership: Membership.leave, + ); + } catch (e) { + Logs() + .e('Chat::_requestParticipants(): Failed to request participants', e); + } + } + bool isUnpinEvent(Event event) => room?.pinnedEventIds .firstWhereOrNull((eventId) => eventId == event.eventId) != @@ -1995,13 +2008,14 @@ class ChatController extends State _tryLoadTimeline(); sendController.addListener(updateInputTextNotifier); super.initState(); - SchedulerBinding.instance.addPostFrameCallback((_) { + SchedulerBinding.instance.addPostFrameCallback((_) async { if (room == null) { return context.go("/error"); } _handleReceivedShareFiles(); _listenRoomUpdateEvent(); initCachedPresence(); + await _requestParticipants(); }); } diff --git a/lib/pages/chat_details/chat_details_page_view/chat_details_members_page.dart b/lib/pages/chat_details/chat_details_page_view/chat_details_members_page.dart index 45bc7f1c87..fd6f90057e 100644 --- a/lib/pages/chat_details/chat_details_page_view/chat_details_members_page.dart +++ b/lib/pages/chat_details/chat_details_page_view/chat_details_members_page.dart @@ -7,21 +7,19 @@ import 'package:matrix/matrix.dart'; class ChatDetailsMembersPage extends StatelessWidget { static const int addMemberItemCount = 1; - final ValueNotifier?> membersNotifier; + final ValueNotifier?> displayMembersNotifier; final int actualMembersCount; final VoidCallback openDialogInvite; final VoidCallback requestMoreMembersAction; final VoidCallback? onUpdatedMembers; - final bool canRequestMoreMembers; final bool isMobileAndTablet; const ChatDetailsMembersPage({ super.key, - required this.membersNotifier, + required this.displayMembersNotifier, required this.actualMembersCount, required this.openDialogInvite, required this.requestMoreMembersAction, - required this.canRequestMoreMembers, required this.isMobileAndTablet, this.onUpdatedMembers, }); @@ -29,9 +27,10 @@ class ChatDetailsMembersPage extends StatelessWidget { @override Widget build(BuildContext context) { return ValueListenableBuilder( - valueListenable: membersNotifier, + valueListenable: displayMembersNotifier, builder: (context, members, child) { members ??= []; + final canRequestMoreMembers = members.length < actualMembersCount; return Column( children: [ Expanded( diff --git a/lib/presentation/mixins/chat_details_tab_mixin.dart b/lib/presentation/mixins/chat_details_tab_mixin.dart index 7390110151..70799b161f 100644 --- a/lib/presentation/mixins/chat_details_tab_mixin.dart +++ b/lib/presentation/mixins/chat_details_tab_mixin.dart @@ -14,7 +14,6 @@ import 'package:fluffychat/presentation/mixins/handle_video_download_mixin.dart' import 'package:fluffychat/presentation/mixins/play_video_action_mixin.dart'; import 'package:fluffychat/presentation/model/chat_details/chat_details_page_model.dart'; import 'package:fluffychat/presentation/same_type_events_builder/same_type_events_controller.dart'; -import 'package:fluffychat/utils/dialog/twake_dialog.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/responsive/responsive_utils.dart'; @@ -36,6 +35,9 @@ mixin ChatDetailsTabMixin final ValueNotifier?> _membersNotifier = ValueNotifier(null); + final ValueNotifier?> _displayMembersNotifier = + ValueNotifier(null); + late final List tabList; Room? get room; @@ -59,6 +61,8 @@ mixin ChatDetailsTabMixin static const _mediaFetchLimit = 20; static const _linksFetchLimit = 20; static const _filesFetchLimit = 20; + static const _maxMembers = 30; + int _currentMembersCount = _maxMembers; static const _memberPageKey = PageStorageKey('members'); static const _mediaPageKey = PageStorageKey('media'); @@ -109,11 +113,36 @@ mixin ChatDetailsTabMixin } void _requestMoreMembersAction() async { - final participants = await TwakeDialog.showFutureLoadingDialogFullScreen( - future: () => room!.requestParticipants(), - ); - if (participants.error == null) { - _membersNotifier.value = participants.result; + final currentMembersCount = _displayMembersNotifier.value?.length ?? 0; + _currentMembersCount += _maxMembers; + + final members = _membersNotifier.value; + if (members != null && currentMembersCount < members.length) { + final endIndex = _currentMembersCount > members.length + ? members.length + : _currentMembersCount; + final newMembers = members.sublist(currentMembersCount, endIndex); + _displayMembersNotifier.value = [ + ...?_displayMembersNotifier.value, + ...newMembers, + ]; + } else { + _displayMembersNotifier.value = [ + ...?_displayMembersNotifier.value, + ...?members, + ]; + } + } + + void _initDisplayMembers() { + final members = _membersNotifier.value; + if (members != null && members.isNotEmpty) { + final endIndex = _currentMembersCount > members.length + ? members.length + : _currentMembersCount; + _displayMembersNotifier.value = members.sublist(0, endIndex); + } else { + _displayMembersNotifier.value = []; } } @@ -188,6 +217,7 @@ mixin ChatDetailsTabMixin void _initMembers() { if (chatType == ChatDetailsScreenEnum.group) { _membersNotifier.value ??= room?.getParticipants(); + _initDisplayMembers(); } } @@ -236,10 +266,8 @@ mixin ChatDetailsTabMixin page: page, child: ChatDetailsMembersPage( key: _memberPageKey, - membersNotifier: _membersNotifier, + displayMembersNotifier: _displayMembersNotifier, actualMembersCount: actualMembersCount, - canRequestMoreMembers: - (_membersNotifier.value?.length ?? 0) < actualMembersCount, requestMoreMembersAction: _requestMoreMembersAction, openDialogInvite: _openDialogInvite, isMobileAndTablet: isMobileAndTablet, @@ -308,6 +336,7 @@ mixin ChatDetailsTabMixin void dispose() { _disposeControllers(); _membersNotifier.dispose(); + _displayMembersNotifier.dispose(); _onRoomEventChangedSubscription?.cancel(); nestedScrollViewState.currentState?.innerController.dispose(); super.dispose(); diff --git a/pubspec.yaml b/pubspec.yaml index d168da58e7..0de34567d1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: matrix: git: url: git@github.com:linagora/matrix-dart-sdk.git - ref: twake-supported-0.22.6 + ref: TW-2165-support-store-members-in-local-database receive_sharing_intent: git: From 66c1d47829a033f5ebd92b792b73bb182a584d1b Mon Sep 17 00:00:00 2001 From: HuyNguyen Date: Mon, 30 Dec 2024 00:46:12 +0700 Subject: [PATCH 2/5] TW-2165: Add ADR for this tick --- ...and-dispay-members-in-group-chat-detail.md | 69 +++++++++++++++++++ pubspec.lock | 4 +- 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 docs/adr/0025-improve-tag-suggesstion-and-dispay-members-in-group-chat-detail.md diff --git a/docs/adr/0025-improve-tag-suggesstion-and-dispay-members-in-group-chat-detail.md b/docs/adr/0025-improve-tag-suggesstion-and-dispay-members-in-group-chat-detail.md new file mode 100644 index 0000000000..d0f8c49f11 --- /dev/null +++ b/docs/adr/0025-improve-tag-suggesstion-and-dispay-members-in-group-chat-detail.md @@ -0,0 +1,69 @@ +# 25. Improve tag suggestion and display members in group chat detail + +**Date:** 2024-12-30 + +## Status + +**Accepted** + +## Context + +- Issue: [#2165](https://github.com/linagora/twake-on-matrix/issues/2165) +- Not all of the members are displayed in the drop-down list when using the tag suggestion feature. +- Can't load more members in the drop-down list when the user scrolls down. + +## Decision + +1.1 **Improve tag suggestion feature** +- When the user go to the group chat, call the func to get the members from server of the group chat. +More details about this logic can be found in the [ADR #0005](https://github.com/linagora/matrix-dart-sdk/blob/cb37032f466004500c98949739720b3b4457cc73/doc/adr/0005-support-store-members-in-hive.md). + +```dart + Future _requestParticipants() async { + if (room == null) return; + try { + await room!.requestParticipants( + at: room!.prev_batch, + notMembership: Membership.leave, + ); + } catch (e) { + Logs() + .e('Chat::_requestParticipants(): Failed to request participants', e); + } + } +``` +- Next time when user go to the group chat, the members will be stored in the hive db and get the members from the hive db to display in the drop-down list. +- When the user types the `@` character, the tag suggestion feature will be triggered. + +1.2 **Display members in the group chat detail** +- When the user clicks on the group chat, how to display the members? + 1. Display members with a maximum size defined by the `_maxMembers` variable defined in `chat_details_tab_mixin.dart`. + ```dart + static const _maxMembers = 30; + ``` + 2. If more members can be loaded, display the Load more button at the end of the list. + 3. When the user clicks on the Load more button, call the function to get more members from the Hive database. + ```dart + void _requestMoreMembersAction() async { + final currentMembersCount = _displayMembersNotifier.value?.length ?? 0; + _currentMembersCount += _maxMembers; + + final members = _membersNotifier.value; + if (members != null && currentMembersCount < members.length) { + final endIndex = _currentMembersCount > members.length + ? members.length + : _currentMembersCount; + final newMembers = members.sublist(currentMembersCount, endIndex); + _displayMembersNotifier.value = [ + ...?_displayMembersNotifier.value, + ...newMembers, + ]; + } else { + _displayMembersNotifier.value = [ + ...?_displayMembersNotifier.value, + ...?members, + ]; + } + } + ``` + 4. Each call only takes a maximum of 30 members according to variable `maxMembers` \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 6663c7865d..cc39acbd91 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1876,8 +1876,8 @@ packages: dependency: "direct main" description: path: "." - ref: "twake-supported-0.22.6" - resolved-ref: "58585a19abc4693d96eab4f8dad9c56bf8699cc1" + ref: TW-2165-support-store-members-in-local-database + resolved-ref: cb37032f466004500c98949739720b3b4457cc73 url: "git@github.com:linagora/matrix-dart-sdk.git" source: git version: "0.22.6" From a8a607ba6dbd65343c8019c5fce2c3f3ef465d47 Mon Sep 17 00:00:00 2001 From: HuyNguyen Date: Mon, 30 Dec 2024 11:01:04 +0700 Subject: [PATCH 3/5] fixup! TW-2165: Add ADR for this tick --- pubspec.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.lock b/pubspec.lock index cc39acbd91..59e02e7e0c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1877,7 +1877,7 @@ packages: description: path: "." ref: TW-2165-support-store-members-in-local-database - resolved-ref: cb37032f466004500c98949739720b3b4457cc73 + resolved-ref: "878b5e873c5196ae0207db762a3253f66a4c337b" url: "git@github.com:linagora/matrix-dart-sdk.git" source: git version: "0.22.6" From 1f0c313fd87a5a6e60a2aa6773b1f47524126647 Mon Sep 17 00:00:00 2001 From: HuyNguyen Date: Fri, 3 Jan 2025 14:37:28 +0700 Subject: [PATCH 4/5] fixup! fixup! TW-2165: Add ADR for this tick --- ...g-suggesstion-and-dispay-members-in-group-chat-detail.md | 6 +++--- lib/presentation/mixins/chat_details_tab_mixin.dart | 6 +++--- pubspec.lock | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/adr/0025-improve-tag-suggesstion-and-dispay-members-in-group-chat-detail.md b/docs/adr/0025-improve-tag-suggesstion-and-dispay-members-in-group-chat-detail.md index d0f8c49f11..2ff91e1fe4 100644 --- a/docs/adr/0025-improve-tag-suggesstion-and-dispay-members-in-group-chat-detail.md +++ b/docs/adr/0025-improve-tag-suggesstion-and-dispay-members-in-group-chat-detail.md @@ -37,16 +37,16 @@ More details about this logic can be found in the [ADR #0005](https://github.com 1.2 **Display members in the group chat detail** - When the user clicks on the group chat, how to display the members? - 1. Display members with a maximum size defined by the `_maxMembers` variable defined in `chat_details_tab_mixin.dart`. + 1. Display members with a maximum size defined by the `_membersPerPage` variable defined in `chat_details_tab_mixin.dart`. ```dart - static const _maxMembers = 30; + static const _membersPerPage = 30; ``` 2. If more members can be loaded, display the Load more button at the end of the list. 3. When the user clicks on the Load more button, call the function to get more members from the Hive database. ```dart void _requestMoreMembersAction() async { final currentMembersCount = _displayMembersNotifier.value?.length ?? 0; - _currentMembersCount += _maxMembers; + _currentMembersCount += _membersPerPage; final members = _membersNotifier.value; if (members != null && currentMembersCount < members.length) { diff --git a/lib/presentation/mixins/chat_details_tab_mixin.dart b/lib/presentation/mixins/chat_details_tab_mixin.dart index 70799b161f..a08e5cd6e5 100644 --- a/lib/presentation/mixins/chat_details_tab_mixin.dart +++ b/lib/presentation/mixins/chat_details_tab_mixin.dart @@ -61,8 +61,8 @@ mixin ChatDetailsTabMixin static const _mediaFetchLimit = 20; static const _linksFetchLimit = 20; static const _filesFetchLimit = 20; - static const _maxMembers = 30; - int _currentMembersCount = _maxMembers; + static const _membersPerPage = 30; + int _currentMembersCount = _membersPerPage; static const _memberPageKey = PageStorageKey('members'); static const _mediaPageKey = PageStorageKey('media'); @@ -114,7 +114,7 @@ mixin ChatDetailsTabMixin void _requestMoreMembersAction() async { final currentMembersCount = _displayMembersNotifier.value?.length ?? 0; - _currentMembersCount += _maxMembers; + _currentMembersCount += _membersPerPage; final members = _membersNotifier.value; if (members != null && currentMembersCount < members.length) { diff --git a/pubspec.lock b/pubspec.lock index 59e02e7e0c..3590062123 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1877,7 +1877,7 @@ packages: description: path: "." ref: TW-2165-support-store-members-in-local-database - resolved-ref: "878b5e873c5196ae0207db762a3253f66a4c337b" + resolved-ref: "5db9aac805dc165508ee10abfe06a4489b98f26a" url: "git@github.com:linagora/matrix-dart-sdk.git" source: git version: "0.22.6" From 1f4bdf1c724490d2b3b09dd1a99337c1bcb7d91f Mon Sep 17 00:00:00 2001 From: HuyNguyen Date: Sat, 4 Jan 2025 23:02:04 +0700 Subject: [PATCH 5/5] fixup! fixup! fixup! TW-2165: Add ADR for this tick --- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 3590062123..6cf7aa5af3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1876,8 +1876,8 @@ packages: dependency: "direct main" description: path: "." - ref: TW-2165-support-store-members-in-local-database - resolved-ref: "5db9aac805dc165508ee10abfe06a4489b98f26a" + ref: "twake-supported-0.22.6" + resolved-ref: ff95aa820c383baf7b808d8df6ebf4d25a3c6c33 url: "git@github.com:linagora/matrix-dart-sdk.git" source: git version: "0.22.6" diff --git a/pubspec.yaml b/pubspec.yaml index 0de34567d1..d168da58e7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: matrix: git: url: git@github.com:linagora/matrix-dart-sdk.git - ref: TW-2165-support-store-members-in-local-database + ref: twake-supported-0.22.6 receive_sharing_intent: git: