From 47c7cb9ee89cbfea2a8186d4e6193e04769da13b Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 16 Sep 2024 02:21:56 +0700 Subject: [PATCH] TF-3123 Fix load more is irrelevant when filtering emails by unread --- .../mailbox_dashboard_controller.dart | 44 ++++--- .../mailbox_dashboard_view_web.dart | 6 +- .../repository/thread_repository_impl.dart | 3 + .../presentation/thread_controller.dart | 119 ++++++++++-------- .../thread/presentation/thread_view.dart | 9 +- 5 files changed, 107 insertions(+), 74 deletions(-) diff --git a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart index b7da72f93..f6b20c268 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -1726,18 +1726,24 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo dispatchAction(StartSearchEmailAction()); } - bool isEmptyTrashBannerEnabledOnWeb(BuildContext context) { - return selectedMailbox.value != null && - selectedMailbox.value!.isTrash && - selectedMailbox.value!.countTotalEmails > 0 && + bool isEmptyTrashBannerEnabledOnWeb( + BuildContext context, + PresentationMailbox? mailbox + ) { + return mailbox != null && + mailbox.isTrash && + mailbox.countTotalEmails > 0 && !searchController.isSearchActive() && responsiveUtils.isWebDesktop(context); } - bool isEmptyTrashBannerEnabledOnMobile(BuildContext context) { - return selectedMailbox.value != null && - selectedMailbox.value!.isTrash && - selectedMailbox.value!.countTotalEmails > 0 && + bool isEmptyTrashBannerEnabledOnMobile( + BuildContext context, + PresentationMailbox? mailbox + ) { + return mailbox != null && + mailbox.isTrash && + mailbox.countTotalEmails > 0 && !searchController.isSearchActive() && !responsiveUtils.isWebDesktop(context); } @@ -2184,18 +2190,24 @@ class MailboxDashBoardController extends ReloadableController with UserSettingPo } } - bool isEmptySpamBannerEnabledOnWeb(BuildContext context) { - return selectedMailbox.value != null && - selectedMailbox.value!.isSpam && - selectedMailbox.value!.countTotalEmails > 0 && + bool isEmptySpamBannerEnabledOnWeb( + BuildContext context, + PresentationMailbox? mailbox + ) { + return mailbox != null && + mailbox.isSpam && + mailbox.countTotalEmails > 0 && !searchController.isSearchActive() && responsiveUtils.isWebDesktop(context); } - bool isEmptySpamBannerEnabledOnMobile(BuildContext context) { - return selectedMailbox.value != null && - selectedMailbox.value!.isSpam && - selectedMailbox.value!.countTotalEmails > 0 && + bool isEmptySpamBannerEnabledOnMobile( + BuildContext context, + PresentationMailbox? mailbox + ) { + return mailbox != null && + mailbox.isSpam && + mailbox.countTotalEmails > 0 && !searchController.isSearchActive() && !responsiveUtils.isWebDesktop(context); } diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart index bcb9e8274..57ec4f22d 100644 --- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart +++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart @@ -95,7 +95,8 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView { ), _buildVacationNotificationMessage(context), Obx(() { - if (controller.isEmptyTrashBannerEnabledOnWeb(context)) { + final presentationMailbox = controller.selectedMailbox.value; + if (controller.isEmptyTrashBannerEnabledOnWeb(context, presentationMailbox)) { return Padding( padding: const EdgeInsetsDirectional.only( top: BannerEmptyTrashStyles.webTopMargin, @@ -110,7 +111,8 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView { } }), Obx(() { - if (controller.isEmptySpamBannerEnabledOnWeb(context)) { + final presentationMailbox = controller.selectedMailbox.value; + if (controller.isEmptySpamBannerEnabledOnWeb(context, presentationMailbox)) { return Padding( padding: const EdgeInsetsDirectional.only( top: BannerDeleteAllSpamEmailsStyles.webTopMargin, diff --git a/lib/features/thread/data/repository/thread_repository_impl.dart b/lib/features/thread/data/repository/thread_repository_impl.dart index 6a29faf5b..b7a5482e9 100644 --- a/lib/features/thread/data/repository/thread_repository_impl.dart +++ b/lib/features/thread/data/repository/thread_repository_impl.dart @@ -277,6 +277,9 @@ class ThreadRepositoryImpl extends ThreadRepository { properties: emailRequest.properties) .then((response) { final listEmails = response.emailList; + if (emailRequest.lastEmailId != null && listEmails?.isNotEmpty == true) { + listEmails?.removeWhere((email) => email.id == emailRequest.lastEmailId); + } return EmailsResponse(emailList: listEmails, state: response.state); }); diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart index 1ea351432..d605c1162 100644 --- a/lib/features/thread/presentation/thread_controller.dart +++ b/lib/features/thread/presentation/thread_controller.dart @@ -1,10 +1,11 @@ +import 'dart:async'; + import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:core/utils/app_logger.dart'; import 'package:core/utils/platform_info.dart'; import 'package:dartz/dartz.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; @@ -110,6 +111,8 @@ class ThreadController extends BaseController with EmailActionController { final FocusNode focusNodeKeyBoard = FocusNode(); final latestEmailSelectedOrUnselected = Rxn(); + StreamSubscription? _resizeBrowserStreamSubscription; + AccountId? get _accountId => mailboxDashBoardController.accountId.value; Session? get _session => mailboxDashBoardController.sessionCurrent; @@ -154,6 +157,9 @@ class ThreadController extends BaseController with EmailActionController { _currentEmailState = null; listEmailController.dispose(); focusNodeKeyBoard.dispose(); + if (PlatformInfo.isWeb) { + _resizeBrowserStreamSubscription?.cancel(); + } super.onClose(); } @@ -230,6 +236,15 @@ class ThreadController extends BaseController with EmailActionController { super.handleUrgentException(failure: failure, exception: exception); } + @override + void onDone() { + viewState.value.map((success) { + if (success is GetAllEmailSuccess) { + _handleOnDoneGetAllEmailSuccess(success); + } + }); + } + void _resetLoadingMore() { if (loadingMoreStatus.value == LoadingMoreStatus.running) { loadingMoreStatus.value = LoadingMoreStatus.idle; @@ -238,7 +253,7 @@ class ThreadController extends BaseController with EmailActionController { void _registerObxStreamListener() { ever(mailboxDashBoardController.selectedMailbox, (mailbox) { - log('ThreadController::_registerObxStreamListener:TEST: SelectedMailbox: ${mailbox?.id} - ${mailbox?.name} | CurrentMemoryMailboxId: $_currentMemoryMailboxId'); + log('ThreadController::_registerObxStreamListener:SelectedMailbox: ${mailbox?.id} - ${mailbox?.name} | CurrentMemoryMailboxId: $_currentMemoryMailboxId'); if (mailbox is PresentationMailbox && mailbox.mailboxId != _currentMemoryMailboxId) { _currentMemoryMailboxId = mailbox.id; @@ -381,23 +396,17 @@ class ThreadController extends BaseController with EmailActionController { } void _registerBrowserResizeListener() { - log('ThreadController::_registerBrowserResizeListener:'); - html.window.onResize.listen((_) => _measureBrowserHeight()); + _resizeBrowserStreamSubscription = html.window.onResize.listen((_) { + _validateBrowserHeight(); + }); } - void _initialMeasureBrowserHeight() { - log('ThreadController::_initialMeasureBrowserHeight:'); - _measureBrowserHeight(); - } - - void _measureBrowserHeight() { + void _validateBrowserHeight() { final browserInnerHeight = html.window.innerHeight ?? 0; - log('ThreadController::_measureBrowserHeight: BROWSER_INTER_HEIGHT = $browserInnerHeight'); final currentListEmails = mailboxDashBoardController.emailsInCurrentMailbox; final totalHeightListEmails = currentListEmails.isEmpty ? 0 : currentListEmails.length * ThreadConstants.defaultMaxHeightEmailItemOnBrowser; - log('ThreadController::_handleResizeBrowser: TOTAL_HEIGHT_LIST_EMAILS = $totalHeightListEmails'); if (browserInnerHeight >= ThreadConstants.defaultMaxHeightBrowser && totalHeightListEmails <= browserInnerHeight) { _performAutomaticallyLoadMoreEmails(); @@ -434,7 +443,7 @@ class ThreadController extends BaseController with EmailActionController { mailboxDashBoardController.emailsInCurrentMailbox.clear(); mailboxDashBoardController.listEmailSelected.clear(); mailboxDashBoardController.currentSelectMode.value = SelectMode.INACTIVE; - canLoadMore = false; + canLoadMore = true; loadingMoreStatus.value = LoadingMoreStatus.idle; } @@ -457,17 +466,15 @@ class ThreadController extends BaseController with EmailActionController { canLoadMore = newListEmail.length >= ThreadConstants.maxCountEmails; - SchedulerBinding.instance.addPostFrameCallback((_) { - if (listEmailController.hasClients) { - listEmailController.animateTo( - 0, - duration: const Duration(milliseconds: 500), - curve: Curves.fastOutSlowIn); - } - if (PlatformInfo.isWeb) { - _initialMeasureBrowserHeight(); - } - }); + if (listEmailController.hasClients) { + listEmailController.jumpTo(0); + } + } + + void _handleOnDoneGetAllEmailSuccess(GetAllEmailSuccess success) { + if (PlatformInfo.isWeb) { + _validateBrowserHeight(); + } } void _refreshChangesAllEmailSuccess(RefreshChangesAllEmailSuccess success) { @@ -494,11 +501,12 @@ class ThreadController extends BaseController with EmailActionController { if (mailboxDashBoardController.emailsInCurrentMailbox.isEmpty) { refreshAllEmail(); } else if (PlatformInfo.isWeb) { - _initialMeasureBrowserHeight(); + _validateBrowserHeight(); } } void _getAllEmailAction() { + log('ThreadController::_getAllEmailAction:'); if (_session != null &&_accountId != null) { consumeState(_getEmailsInMailboxInteractor.execute( _session!, @@ -598,11 +606,12 @@ class ThreadController extends BaseController with EmailActionController { } void _loadMoreEmails() { - log('ThreadController::_loadMoreEmails()'); + log('ThreadController::_loadMoreEmails()::canLoadMore = $canLoadMore'); if (canLoadMore && _session != null && _accountId != null) { final oldestEmail = mailboxDashBoardController.emailsInCurrentMailbox.isNotEmpty ? mailboxDashBoardController.emailsInCurrentMailbox.last : null; + log('ThreadController::_loadMoreEmails: OldestEmailID = ${oldestEmail?.id?.asString}'); consumeState(_loadMoreEmailsInMailboxInteractor.execute( GetEmailRequest( _session!, @@ -619,8 +628,13 @@ class ThreadController extends BaseController with EmailActionController { } } + bool _validatePresentationEmail(PresentationEmail email) { + return _belongToCurrentMailboxId(email) + && _notDuplicatedInCurrentList(email); + } + bool _belongToCurrentMailboxId(PresentationEmail email) { - return (email.mailboxIds != null && email.mailboxIds!.keys.contains(selectedMailboxId)); + return email.mailboxIds != null && email.mailboxIds!.keys.contains(selectedMailboxId); } bool _notDuplicatedInCurrentList(PresentationEmail email) { @@ -630,29 +644,31 @@ class ThreadController extends BaseController with EmailActionController { } void _loadMoreEmailsSuccess(LoadMoreEmailsSuccess success) { - log('ThreadController::_loadMoreEmailsSuccess: COUNT = ${success.emailList.length}'); - if (success.emailList.isNotEmpty) { - final appendableList = success.emailList - .where(_belongToCurrentMailboxId) - .where(_notDuplicatedInCurrentList) - .toList() - .syncPresentationEmail( - mapMailboxById: mailboxDashBoardController.mapMailboxById, - selectedMailbox: selectedMailbox, - searchQuery: searchController.searchQuery, - isSearchEmailRunning: searchController.isSearchEmailRunning - ); - - mailboxDashBoardController.emailsInCurrentMailbox.addAll(appendableList); - canLoadMore = true; - } else { - canLoadMore = false; - } + canLoadMore = success.emailList.isNotEmpty; loadingMoreStatus.value = LoadingMoreStatus.completed; - - if (PlatformInfo.isWeb) { - _initialMeasureBrowserHeight(); + final appendableList = validateListEmailsLoadMore(success.emailList); + log('ThreadController::_loadMoreEmailsSuccess: emailList = ${success.emailList.length} | appendableList = ${appendableList.length}'); + if (appendableList.isNotEmpty) { + mailboxDashBoardController.emailsInCurrentMailbox.addAll(appendableList); } + if (PlatformInfo.isWeb) { + _validateBrowserHeight(); + } + } + + List validateListEmailsLoadMore(List emailList) { + log('ThreadController::validateListEmailsLoadMore: BEFORE_EMAIL_LIST = ${emailList.length}'); + final appendableList = emailList + .where(_validatePresentationEmail) + .toList() + .syncPresentationEmail( + mapMailboxById: mailboxDashBoardController.mapMailboxById, + selectedMailbox: selectedMailbox, + searchQuery: searchController.searchQuery, + isSearchEmailRunning: searchController.isSearchEmailRunning + ); + log('ThreadController::validateListEmailsLoadMore: AFTER_EMAIL_LIST = ${appendableList.length}'); + return appendableList; } SelectMode getSelectMode(PresentationEmail presentationEmail, PresentationEmail? selectedEmail) { @@ -787,9 +803,6 @@ class ThreadController extends BaseController with EmailActionController { bool get isSearchActive => searchController.isSearchEmailRunning; - bool get isAllSearchInActive => !searchController.isSearchActive() && - searchController.isAdvancedSearchViewOpen.isFalse; - void clearTextSearch() { searchController.clearTextSearch(); } @@ -870,7 +883,7 @@ class ThreadController extends BaseController with EmailActionController { canSearchMore = newEmailListSynced.length >= ThreadConstants.maxCountEmails; if (PlatformInfo.isWeb) { - _initialMeasureBrowserHeight(); + _validateBrowserHeight(); } } @@ -929,7 +942,7 @@ class ThreadController extends BaseController with EmailActionController { loadingMoreStatus.value = LoadingMoreStatus.completed; if (PlatformInfo.isWeb) { - _initialMeasureBrowserHeight(); + _validateBrowserHeight(); } } diff --git a/lib/features/thread/presentation/thread_view.dart b/lib/features/thread/presentation/thread_view.dart index 9992a9e10..08a726e64 100644 --- a/lib/features/thread/presentation/thread_view.dart +++ b/lib/features/thread/presentation/thread_view.dart @@ -143,7 +143,8 @@ class ThreadView extends GetWidget )), ], Obx(() { - if (controller.mailboxDashBoardController.isEmptyTrashBannerEnabledOnMobile(context)) { + final presentationMailbox = controller.mailboxDashBoardController.selectedMailbox.value; + if (controller.mailboxDashBoardController.isEmptyTrashBannerEnabledOnMobile(context, presentationMailbox)) { return Padding( padding: const EdgeInsetsDirectional.symmetric( horizontal: BannerEmptyTrashStyles.mobileMargin @@ -157,7 +158,8 @@ class ThreadView extends GetWidget } }), Obx(() { - if (controller.mailboxDashBoardController.isEmptySpamBannerEnabledOnMobile(context)) { + final presentationMailbox = controller.mailboxDashBoardController.selectedMailbox.value; + if (controller.mailboxDashBoardController.isEmptySpamBannerEnabledOnMobile(context, presentationMailbox)) { return Padding( padding: const EdgeInsetsDirectional.symmetric( horizontal: BannerDeleteAllSpamEmailsStyles.mobileMargin @@ -305,7 +307,8 @@ class ThreadView extends GetWidget } return Obx(() { - if (controller.isAllSearchInActive) { + final isAdvancedSearchViewOpen = controller.searchController.isAdvancedSearchViewOpen.value; + if (controller.searchController.isSearchActive() && !isAdvancedSearchViewOpen) { return Container( padding: PlatformInfo.isMobile && controller.listEmailSelected.isNotEmpty ? EdgeInsets.only(bottom: controller.responsiveUtils.isTabletLarge(context) ? 85 : 70)