TF-996: add previous / Next message of a mailbox on mobile/tablet

This commit is contained in:
ManhNTX
2022-10-27 16:23:36 +07:00
committed by Dat H. Pham
parent 93afb42c1b
commit bc102dd9ec
6 changed files with 94 additions and 30 deletions
@@ -0,0 +1,25 @@
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/model.dart';
class EmailLoaded with EquatableMixin {
final List<EmailContent> emailContents;
final List<EmailContent> emailContentsDisplayed;
final List<Attachment> attachments;
final Email? emailCurrent;
EmailLoaded(
this.emailContents,
this.emailContentsDisplayed,
this.attachments,
this.emailCurrent
);
@override
List<Object?> get props => [
emailContents,
emailContentsDisplayed,
attachments,
emailCurrent
];
}
@@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.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/state/get_email_content_state.dart';
@@ -12,31 +13,41 @@ class GetEmailContentInteractor {
GetEmailContentInteractor(this.emailRepository);
Stream<Either<Failure, Success>> execute(AccountId accountId, EmailId emailId, String? baseDownloadUrl) async* {
Stream<Either<Failure, Success>> execute(AccountId accountId, EmailId emailId, String? baseDownloadUrl, {EmailLoaded? emailLoaded}) async* {
try {
yield Right<Failure, Success>(GetEmailContentLoading());
final email = await emailRepository.getEmailContent(accountId, emailId);
if (email.emailContentList.isNotEmpty) {
final newEmailContents = await emailRepository.transformEmailContent(
email.emailContentList,
email.allAttachments.listAttachmentsDisplayedInContent,
baseDownloadUrl,
accountId);
final newEmailContentsDisplayed = kIsWeb
? await emailRepository.addTooltipWhenHoverOnLink(newEmailContents)
: newEmailContents;
if(emailLoaded != null) {
await Future.delayed(const Duration(milliseconds: 300));
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));
emailLoaded.emailContents,
emailLoaded.emailContentsDisplayed,
emailLoaded.attachments,
emailLoaded.emailCurrent));
} else {
yield Left(GetEmailContentFailure(null));
final email = await emailRepository.getEmailContent(accountId, emailId);
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) {
log('GetEmailContentInteractor::execute(): exception = $e');
@@ -26,6 +26,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/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/email/domain/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_to_mailbox_request.dart';
import 'package:tmail_ui_user/features/email/domain/model/send_receipt_to_sender_request.dart';
@@ -89,9 +90,9 @@ class EmailController extends BaseController with AppLoaderMixin {
EmailId? _currentEmailId;
Identity? _identitySelected;
List<EmailContent>? initialEmailContents;
late Worker emailWorker;
final Map<EmailId, EmailLoaded> presentationEmailsLoaded = {};
PageController? pageController;
final StreamController<Either<Failure, Success>> _downloadProgressStateController =
StreamController<Either<Failure, Success>>.broadcast();
Stream<Either<Failure, Success>> get downloadProgressState => _downloadProgressStateController.stream;
@@ -141,18 +142,29 @@ class EmailController extends BaseController with AppLoaderMixin {
super.onClose();
}
void _setCurrentPositionEmailInListEmail() {
pageController ??= PageController(initialPage: mailboxDashBoardController.emailList.indexOf(mailboxDashBoardController.selectedEmail.value));
}
void onPageChanged(int index) {
mailboxDashBoardController.selectedEmail.value = mailboxDashBoardController.emailList[index];
}
void _initWorker() {
emailWorker = ever(mailboxDashBoardController.selectedEmail, (presentationEmail) {
log('EmailController::_initWorker(): $presentationEmail');
if (presentationEmail is PresentationEmail) {
if (_currentEmailId != presentationEmail.id) {
_setCurrentPositionEmailInListEmail();
if (_currentEmailId != presentationEmail.id) {
_currentEmailId = presentationEmail.id;
_resetToOriginalValue();
_getEmailContentAction(presentationEmail.id);
if (!presentationEmail.hasRead) {
markAsEmailRead(presentationEmail, ReadActions.markAsRead);
}
_getAllIdentities();
if(_identitySelected == null) {
_getAllIdentities();
}
}
}
});
@@ -222,8 +234,13 @@ class EmailController extends BaseController with AppLoaderMixin {
void _getEmailContentAction(EmailId emailId) async {
final accountId = mailboxDashBoardController.accountId.value;
final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl();
final listEmailIdLoaded = presentationEmailsLoaded.keys.toList();
EmailLoaded? emailLoaded;
if(listEmailIdLoaded.contains(_currentEmailId)) {
emailLoaded = presentationEmailsLoaded[_currentEmailId];
}
if (accountId != null && baseDownloadUrl != null) {
consumeState(_getEmailContentInteractor.execute(accountId, emailId, baseDownloadUrl));
consumeState(_getEmailContentInteractor.execute(accountId, emailId, baseDownloadUrl, emailLoaded: emailLoaded));
}
}
@@ -263,6 +280,7 @@ class EmailController extends BaseController with AppLoaderMixin {
}
void _getEmailContentSuccess(GetEmailContentSuccess success) {
presentationEmailsLoaded[success.emailCurrent!.id] = EmailLoaded(success.emailContents.toList(), success.emailContentsDisplayed.toList(), success.attachments.toList(), success.emailCurrent);
emailContents.value = success.emailContentsDisplayed;
initialEmailContents = success.emailContents;
attachments.value = success.attachments;
@@ -48,9 +48,9 @@ class EmailView extends GetWidget<EmailController> {
child: Container(
decoration: responsiveUtils.isWebDesktop(context)
? BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(color: AppColor.colorBorderBodyThread, width: 1),
color: Colors.white)
borderRadius: BorderRadius.circular(20),
border: Border.all(color: AppColor.colorBorderBodyThread, width: 1),
color: Colors.white)
: const BoxDecoration(color: Colors.white),
margin: _getMarginEmailView(context),
child: Obx(() {
@@ -89,7 +89,15 @@ class EmailView extends GetWidget<EmailController> {
_buildAppBar(context, email),
_buildVacationNotificationMessage(context),
const Divider(color: AppColor.colorDividerHorizontal, height: 1),
Expanded(child: _buildEmailBody(context, email)),
Expanded(
child: PageView.builder(
itemCount: controller.mailboxDashBoardController.emailList.length,
controller: controller.pageController,
onPageChanged: controller.onPageChanged,
itemBuilder: (context, _) {
return _buildEmailBody(context, email);
}),
),
const Divider(color: AppColor.colorDividerHorizontal, height: 1),
_buildBottomBar(context, email),
]);
@@ -126,6 +126,7 @@ class MailboxDashBoardController extends ReloadableController {
Session? sessionCurrent;
Map<Role, MailboxId> mapDefaultMailboxIdByRole = {};
Map<MailboxId, PresentationMailbox> mapMailboxById = {};
final emailList = <PresentationEmail>[].obs;
PresentationMailbox? outboxMailbox;
RouterArguments? routerArguments;
@@ -99,7 +99,6 @@ class ThreadController extends BaseController {
final MoveToMailboxInteractor _moveToMailboxInteractor;
final CachingManager _cachingManager;
final emailList = <PresentationEmail>[].obs;
final listEmailDrag = <PresentationEmail>[].obs;
bool canLoadMore = true;
@@ -128,6 +127,8 @@ class ThreadController extends BaseController {
SearchQuery? get searchQuery => searchController.searchEmailFilter.value.text;
RxList<PresentationEmail> get emailList => mailboxDashBoardController.emailList;
ThreadController(
this._getEmailsInMailboxInteractor,
this._markAsMultipleEmailReadInteractor,