TF-996: Previous / Next message when searching email

This commit is contained in:
ManhNTX
2022-10-28 18:46:19 +07:00
committed by Dat H. Pham
parent 4e3385dc84
commit 2e16cc7f6c
6 changed files with 61 additions and 53 deletions
@@ -4,7 +4,6 @@ import 'package:flutter/foundation.dart';
import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
import 'package:tmail_ui_user/features/email/domain/model/email_loaded.dart';
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
@@ -13,41 +12,31 @@ class GetEmailContentInteractor {
GetEmailContentInteractor(this.emailRepository); GetEmailContentInteractor(this.emailRepository);
Stream<Either<Failure, Success>> execute(AccountId accountId, EmailId emailId, String? baseDownloadUrl, {EmailLoaded? emailLoaded}) async* { Stream<Either<Failure, Success>> execute(AccountId accountId, EmailId emailId, String? baseDownloadUrl) async* {
try { try {
yield Right<Failure, Success>(GetEmailContentLoading()); yield Right<Failure, Success>(GetEmailContentLoading());
final email = await emailRepository.getEmailContent(accountId, emailId);
if(emailLoaded != null) { if (email.emailContentList.isNotEmpty) {
await Future.delayed(const Duration(milliseconds: 300)); final newEmailContents = await emailRepository.transformEmailContent(
email.emailContentList,
email.allAttachments.listAttachmentsDisplayedInContent,
baseDownloadUrl,
accountId);
final newEmailContentsDisplayed = kIsWeb
? await emailRepository.addTooltipWhenHoverOnLink(newEmailContents)
: newEmailContents;
yield Right<Failure, Success>(GetEmailContentSuccess( yield Right<Failure, Success>(GetEmailContentSuccess(
emailLoaded.emailContents, newEmailContents,
emailLoaded.emailContentsDisplayed, newEmailContentsDisplayed,
emailLoaded.attachments, email.allAttachments,
emailLoaded.emailCurrent)); email));
} else if (email.allAttachments.isNotEmpty) {
yield Right<Failure, Success>(GetEmailContentSuccess([], [], email.allAttachments, email));
} else if (email.headers?.isNotEmpty == true) {
yield Right<Failure, Success>(GetEmailContentSuccess([], [], [], email));
} else { } else {
final email = await emailRepository.getEmailContent(accountId, emailId); yield Left(GetEmailContentFailure(null));
if (email.emailContentList.isNotEmpty) {
final newEmailContents = await emailRepository.transformEmailContent(
email.emailContentList,
email.allAttachments.listAttachmentsDisplayedInContent,
baseDownloadUrl,
accountId);
final newEmailContentsDisplayed = kIsWeb
? await emailRepository.addTooltipWhenHoverOnLink(newEmailContents)
: newEmailContents;
yield Right<Failure, Success>(GetEmailContentSuccess(
newEmailContents,
newEmailContentsDisplayed,
email.allAttachments,
email));
} else if (email.allAttachments.isNotEmpty) {
yield Right<Failure, Success>(GetEmailContentSuccess([], [], email.allAttachments, email));
} else if (email.headers?.isNotEmpty == true) {
yield Right<Failure, Success>(GetEmailContentSuccess([], [], [], email));
} else {
yield Left(GetEmailContentFailure(null));
}
} }
} catch (e) { } catch (e) {
log('GetEmailContentInteractor::execute(): exception = $e'); log('GetEmailContentInteractor::execute(): exception = $e');
@@ -6,6 +6,7 @@ import 'package:core/core.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
@@ -27,7 +28,7 @@ import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart'; import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart'; import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
import 'package:tmail_ui_user/features/email/domain/model/email_loaded.dart'; import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_action.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_action.dart';
import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/move_to_mailbox_request.dart';
import 'package:tmail_ui_user/features/email/domain/model/send_receipt_to_sender_request.dart'; import 'package:tmail_ui_user/features/email/domain/model/send_receipt_to_sender_request.dart';
@@ -57,6 +58,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/down
import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_identities_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_identities_state.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/datetime_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/extensions/datetime_extension.dart';
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/delete_action_type.dart'; import 'package:tmail_ui_user/features/thread/presentation/model/delete_action_type.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart';
@@ -107,6 +109,10 @@ class EmailController extends BaseController with AppLoaderMixin {
bool get isDisplayFullAttachments => attachmentsExpandMode.value == ExpandMode.EXPAND; bool get isDisplayFullAttachments => attachmentsExpandMode.value == ExpandMode.EXPAND;
RxList<PresentationEmail> get listEmail => mailboxDashBoardController.searchController.isSearchEmailRunning && !kIsWeb ?
mailboxDashBoardController.listResultSearch : mailboxDashBoardController.emailsInCurrentMailbox;
EmailController( EmailController(
this._getEmailContentInteractor, this._getEmailContentInteractor,
this._markAsEmailReadInteractor, this._markAsEmailReadInteractor,
@@ -147,8 +153,8 @@ class EmailController extends BaseController with AppLoaderMixin {
super.onClose(); super.onClose();
} }
void _setCurrentPositionEmailInListEmail() { void _setCurrentPositionEmailInListEmail(EmailId? currentEmailId) {
currentIndexPageView = mailboxDashBoardController.emailsInCurrentMailbox.indexOf(mailboxDashBoardController.selectedEmail.value); currentIndexPageView = listEmail.indexWhere((e) => e.id == currentEmailId);
if(pageController != null && pageController!.hasClients && pageController!.page?.toInt() != currentIndexPageView) { if(pageController != null && pageController!.hasClients && pageController!.page?.toInt() != currentIndexPageView) {
pageController!.jumpToPage(currentIndexPageView); pageController!.jumpToPage(currentIndexPageView);
} else { } else {
@@ -158,12 +164,12 @@ class EmailController extends BaseController with AppLoaderMixin {
} }
void onPageChanged(int index) { void onPageChanged(int index) {
mailboxDashBoardController.selectedEmail.value = mailboxDashBoardController.emailsInCurrentMailbox[index]; mailboxDashBoardController.selectedEmail.value = listEmail[index];
} }
void _checkEnableNavigatorPageView() { void _checkEnableNavigatorPageView() {
canGetNewerEmail.value = currentIndexPageView > 0; canGetNewerEmail.value = currentIndexPageView > 0;
canGetOlderEmail.value = mailboxDashBoardController.emailsInCurrentMailbox.length > 1 && currentIndexPageView < mailboxDashBoardController.emailsInCurrentMailbox.length - 1; canGetOlderEmail.value = listEmail.length > 1 && currentIndexPageView < listEmail.length - 1;
} }
void getNewerEmail() { void getNewerEmail() {
@@ -180,9 +186,9 @@ class EmailController extends BaseController with AppLoaderMixin {
emailWorker = ever(mailboxDashBoardController.selectedEmail, (presentationEmail) { emailWorker = ever(mailboxDashBoardController.selectedEmail, (presentationEmail) {
log('EmailController::_initWorker(): $presentationEmail'); log('EmailController::_initWorker(): $presentationEmail');
if (presentationEmail is PresentationEmail) { if (presentationEmail is PresentationEmail) {
_setCurrentPositionEmailInListEmail();
if (_currentEmailId != presentationEmail.id) { if (_currentEmailId != presentationEmail.id) {
_currentEmailId = presentationEmail.id; _currentEmailId = presentationEmail.id;
_setCurrentPositionEmailInListEmail(_currentEmailId);
_resetToOriginalValue(); _resetToOriginalValue();
_getEmailContentAction(presentationEmail.id); _getEmailContentAction(presentationEmail.id);
if (!presentationEmail.hasRead) { if (!presentationEmail.hasRead) {
@@ -260,13 +266,19 @@ class EmailController extends BaseController with AppLoaderMixin {
void _getEmailContentAction(EmailId emailId) async { void _getEmailContentAction(EmailId emailId) async {
final accountId = mailboxDashBoardController.accountId.value; final accountId = mailboxDashBoardController.accountId.value;
final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl(); final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl();
final listEmailIdLoaded = presentationEmailsLoaded.map((e) => e.emailCurrent!.id).toList(); final currentEmail = presentationEmailsLoaded.where((e) => e.emailCurrent!.id == emailId);
EmailLoaded? emailLoaded; EmailLoaded? emailLoaded;
if(listEmailIdLoaded.contains(_currentEmailId)) { if(currentEmail.isNotEmpty) {
emailLoaded = presentationEmailsLoaded.firstWhere((e) => e.emailCurrent!.id == _currentEmailId); emailLoaded = currentEmail.first;
} dispatchState(Right<Failure, Success>(GetEmailContentLoading()));
if (accountId != null && baseDownloadUrl != null) { await Future.delayed(const Duration(milliseconds: 300));
consumeState(_getEmailContentInteractor.execute(accountId, emailId, baseDownloadUrl, emailLoaded: emailLoaded)); consumeState(Stream.value(Right<Failure, Success>(GetEmailContentSuccess(
emailLoaded.emailContents,
emailLoaded.emailContentsDisplayed,
emailLoaded.attachments,
emailLoaded.emailCurrent))));
} else if (accountId != null && baseDownloadUrl != null) {
consumeState(_getEmailContentInteractor.execute(accountId, emailId, baseDownloadUrl));
} }
} }
@@ -306,11 +318,16 @@ class EmailController extends BaseController with AppLoaderMixin {
} }
void _getEmailContentSuccess(GetEmailContentSuccess success) { void _getEmailContentSuccess(GetEmailContentSuccess success) {
if(presentationEmailsLoaded.length > 100) { if(presentationEmailsLoaded.length > ThreadConstants.defaultLimit.value.toInt()) {
presentationEmailsLoaded.removeFirst(); presentationEmailsLoaded.removeFirst();
} }
final emailLoaded = EmailLoaded(success.emailContents.toList(), success.emailContentsDisplayed.toList(), success.attachments.toList(), success.emailCurrent); final emailLoaded = EmailLoaded(
presentationEmailsLoaded.removeWhere((e) => e.emailCurrent!.id == emailLoaded.emailCurrent!.id); success.emailContents.toList(),
success.emailContentsDisplayed.toList(),
success.attachments.toList(),
success.emailCurrent,
);
presentationEmailsLoaded.removeWhere((e) => e == emailLoaded);
presentationEmailsLoaded.add(emailLoaded); presentationEmailsLoaded.add(emailLoaded);
emailContents.value = success.emailContentsDisplayed; emailContents.value = success.emailContentsDisplayed;
initialEmailContents = success.emailContents; initialEmailContents = success.emailContents;
@@ -93,7 +93,7 @@ class EmailView extends GetWidget<EmailController> {
Expanded( Expanded(
child: PageView.builder( child: PageView.builder(
physics: kIsWeb ? const NeverScrollableScrollPhysics() : null, physics: kIsWeb ? const NeverScrollableScrollPhysics() : null,
itemCount: controller.mailboxDashBoardController.emailsInCurrentMailbox.length, itemCount: controller.listEmail.length,
controller: controller.pageController, controller: controller.pageController,
onPageChanged: controller.onPageChanged, onPageChanged: controller.onPageChanged,
itemBuilder: (context, _) { itemBuilder: (context, _) {
@@ -9,11 +9,11 @@ class EmailLoaded with EquatableMixin {
final Email? emailCurrent; final Email? emailCurrent;
EmailLoaded( EmailLoaded(
this.emailContents, this.emailContents,
this.emailContentsDisplayed, this.emailContentsDisplayed,
this.attachments, this.attachments,
this.emailCurrent this.emailCurrent,
); );
@override @override
List<Object?> get props => [ List<Object?> get props => [
@@ -127,6 +127,7 @@ class MailboxDashBoardController extends ReloadableController {
Map<Role, MailboxId> mapDefaultMailboxIdByRole = {}; Map<Role, MailboxId> mapDefaultMailboxIdByRole = {};
Map<MailboxId, PresentationMailbox> mapMailboxById = {}; Map<MailboxId, PresentationMailbox> mapMailboxById = {};
final emailsInCurrentMailbox = <PresentationEmail>[].obs; final emailsInCurrentMailbox = <PresentationEmail>[].obs;
final listResultSearch = RxList<PresentationEmail>();
PresentationMailbox? outboxMailbox; PresentationMailbox? outboxMailbox;
RouterArguments? routerArguments; RouterArguments? routerArguments;
@@ -71,7 +71,6 @@ class SearchEmailController extends BaseController
final currentSearchText = RxString(''); final currentSearchText = RxString('');
final listRecentSearch = RxList<RecentSearch>(); final listRecentSearch = RxList<RecentSearch>();
final listSuggestionSearch = RxList<PresentationEmail>(); final listSuggestionSearch = RxList<PresentationEmail>();
final listResultSearch = RxList<PresentationEmail>();
final simpleSearchFilter = Rx<SimpleSearchFilter>(SimpleSearchFilter()); final simpleSearchFilter = Rx<SimpleSearchFilter>(SimpleSearchFilter());
final searchIsRunning = RxBool(false); final searchIsRunning = RxBool(false);
final emailReceiveTimeType = Rxn<EmailReceiveTimeType>(); final emailReceiveTimeType = Rxn<EmailReceiveTimeType>();
@@ -92,6 +91,8 @@ class SearchEmailController extends BaseController
SearchQuery? get searchQuery => simpleSearchFilter.value.text; SearchQuery? get searchQuery => simpleSearchFilter.value.text;
RxList<PresentationEmail> get listResultSearch => mailboxDashBoardController.listResultSearch;
SearchEmailController( SearchEmailController(
this._quickSearchEmailInteractor, this._quickSearchEmailInteractor,
this._saveRecentSearchInteractor, this._saveRecentSearchInteractor,