TF-3715 Thread Detail create resuable actions
TF-3715 Thread Detail refactor actions for expanded email view TF-3715 Thread Detail apply actions for collapsed email view TF-3715 Thread Detail fix unit tests TF-3715 Thread Detail add await for _getEmailContent in composer TF-3715 Thread Detail remove unused emailLoaded in ThreadDetailAppBar TF-3715 Thread Detail hide print action when isMobile TF-3715 Thread Detail allow mark as read in EmailActionReactor TF-3715 Thread Detail fix loadMoreThreadDetailEmails unit test TF-3715 Thread Detail fix action small tap region TF-3715 Thread Detail fix cannot permanent delete email TF-3715 Thread Detail prevent close when move email TF-3715 Thread Detail fix refresh when mark star selected collapsed email TF-3715 Thread Detail update print action display logic TF-3715 Thread Detail fix duplicate mark star in app bar TF-3715 Thread Detail create new transformer for reply forward empty content email TF-3715 Thread Detail fix email not load after open multiple times TF-3715 Thread Detail fix close when move expanded email TF-3715 Thread Detail fix duplicate and missing actions TF-3715 Thread Detail restore editAsNewEmail action to _getEmailContent in setupEmailContent TF-3715 Thread Detail update print action name TF-3715 Thread Detail handle move and delete email with 1 item in thread detail TF-3715 Thread Detail fix tap outside to close context menu TF-3715 Thread Detail fix create rule and compose from recipient info TF-3715 Thread Detail handle move and delete email with 1 item in thread detail TF-3715 Thread Detail Fix cannot create email rule TF-3715 Thread Detail Fix crash composer TF-3715 Thread Detail Fix cannot unsubscribe TF-3715 Thread Detail Fix duplicate actions on single email TF-3715 Thread Detail Fix refresh view when reply/forward TF-3715 Thread Detail Revert old logic to _getEmailContent TF-3715 Thread Detail Update specific cases for UpdatedEmailKeywordsAction TF-3715 Thread Detail Fix concurrent modification during iteration TF-3715 Thread Detail Fix unsubscribe for all thread detail emails TF-3715 Thread Detail Remove unnecessary Future in reactor TF-3715 Thread Detail Remove dependency from SingleEmailController TF-3715 Thread Detail Apply individual list post and unsubscribe header TF-3715 Thread Detail Fix unsubscribe collapsed email TF-3715 Thread Detail Conditionally inject rule filter interactor
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
||||
import 'package:tmail_ui_user/features/base/action/ui_action.dart';
|
||||
|
||||
class ThreadDetailUIAction extends UIAction {
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class UpdatedEmailKeywordsAction extends ThreadDetailUIAction {
|
||||
UpdatedEmailKeywordsAction(
|
||||
this.emailId,
|
||||
this.updatedKeyword,
|
||||
this.value,
|
||||
);
|
||||
|
||||
final EmailId emailId;
|
||||
final KeyWordIdentifier updatedKeyword;
|
||||
final bool value;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [emailId, updatedKeyword, value];
|
||||
}
|
||||
@@ -10,10 +10,11 @@ extension CloseThreadDetailAction on ThreadDetailController {
|
||||
} else {
|
||||
mailboxDashBoardController.dispatchRoute(DashboardRoutes.thread);
|
||||
}
|
||||
for (var emailId in emailIdsPresentation.keys) {
|
||||
mailboxDashBoardController.dispatchEmailUIAction(
|
||||
CloseEmailInThreadDetailAction(emailId),
|
||||
);
|
||||
final cleanUpEmailIds = List.from(emailIdsPresentation.keys);
|
||||
for (var emailId in cleanUpEmailIds) {
|
||||
mailboxDashBoardController
|
||||
..dispatchEmailUIAction(CloseEmailInThreadDetailAction(emailId))
|
||||
..dispatchEmailUIAction(EmailUIAction());
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
+36
-3
@@ -1,12 +1,18 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:model/extensions/presentation_email_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
|
||||
import 'package:model/email/email_in_thread_status.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/get_mailbox_contain_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/load_more_thread_detail_emails.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/thread_detail_on_email_action_click.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/thread_detail_open_email_address_detail_action.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/toggle_thread_detail_collape_expand.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/widgets/thread_detail_collapsed_email.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/widgets/thread_detail_load_more_circle.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
extension GetThreadDetailEmailViews on ThreadDetailController {
|
||||
List<Widget> getThreadDetailEmailViews() {
|
||||
@@ -58,10 +64,37 @@ extension GetThreadDetailEmailViews on ThreadDetailController {
|
||||
showSubject: isFirstEmailInThreadDetail,
|
||||
imagePaths: imagePaths,
|
||||
responsiveUtils: responsiveUtils,
|
||||
mailboxContain: presentationEmail.mailboxContain,
|
||||
mailboxContain: presentationEmail.findMailboxContain(
|
||||
mailboxDashBoardController.mapMailboxById,
|
||||
),
|
||||
emailLoaded: null,
|
||||
openEmailAddressDetailAction: (context, emailAddress) {
|
||||
// TODO: Next PR
|
||||
onEmailActionClick: threadDetailOnEmailActionClick,
|
||||
onMoreActionClick: (presentationEmail, position) => emailActionReactor.handleMoreEmailAction(
|
||||
mailboxContain: mailboxDashBoardController.getMailboxContain(presentationEmail),
|
||||
presentationEmail: presentationEmail,
|
||||
position: position,
|
||||
responsiveUtils: responsiveUtils,
|
||||
imagePaths: imagePaths,
|
||||
username: session?.username,
|
||||
handleEmailAction: threadDetailOnEmailActionClick,
|
||||
additionalActions: [
|
||||
EmailActionType.forward,
|
||||
EmailActionType.replyAll,
|
||||
EmailActionType.replyToList,
|
||||
EmailActionType.printAll,
|
||||
if (currentContext != null &&
|
||||
responsiveUtils.isMobile(currentContext!))
|
||||
EmailActionType.moveToMailbox,
|
||||
if (!responsiveUtils.isDesktop(currentContext!)) ...[
|
||||
EmailActionType.markAsStarred,
|
||||
EmailActionType.unMarkAsStarred,
|
||||
EmailActionType.moveToTrash,
|
||||
EmailActionType.deletePermanently,
|
||||
],
|
||||
],
|
||||
),
|
||||
openEmailAddressDetailAction: (_, emailAddress) {
|
||||
openEmailAddressDetailAction(emailAddress);
|
||||
},
|
||||
onToggleThreadDetailCollapseExpand: () {
|
||||
toggleThreadDetailCollapeExpand(presentationEmail);
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/download/download_task_state.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
extension HandleCollapsedEmailDownloadStates on ThreadDetailController {
|
||||
void handleDownloadProgressState(Either<Failure, Success> state) {
|
||||
state.fold(
|
||||
(failure) => null,
|
||||
(success) {
|
||||
if (success is StartDownloadAttachmentForWeb &&
|
||||
!success.previewerSupported
|
||||
) {
|
||||
mailboxDashBoardController.addDownloadTask(
|
||||
DownloadTaskState(
|
||||
taskId: success.taskId,
|
||||
attachment: success.attachment,
|
||||
onCancel: () => success.cancelToken?.cancel(),
|
||||
),
|
||||
);
|
||||
|
||||
if (currentOverlayContext != null &&
|
||||
currentContext != null &&
|
||||
!success.previewerSupported
|
||||
) {
|
||||
appToast.showToastMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).your_download_has_started,
|
||||
leadingSVGIconColor: AppColor.primaryColor,
|
||||
leadingSVGIcon: imagePaths.icDownload,
|
||||
);
|
||||
}
|
||||
} else if (success is DownloadingAttachmentForWeb) {
|
||||
mailboxDashBoardController.updateDownloadTask(
|
||||
success.taskId,
|
||||
(currentTask) {
|
||||
final newTask = currentTask.copyWith(
|
||||
progress: success.progress,
|
||||
downloaded: success.downloaded,
|
||||
total: success.total,
|
||||
);
|
||||
|
||||
return newTask;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void handleDownloadSuccess(DownloadAttachmentForWebSuccess success) {
|
||||
mailboxDashBoardController.deleteDownloadTask(success.taskId);
|
||||
|
||||
downloadManager.createAnchorElementDownloadFileWeb(
|
||||
success.bytes,
|
||||
success.attachment.generateFileName());
|
||||
}
|
||||
|
||||
void handleDownloadFailure(DownloadAttachmentForWebFailure failure) {
|
||||
if (failure.taskId != null) {
|
||||
mailboxDashBoardController.deleteDownloadTask(failure.taskId!);
|
||||
}
|
||||
|
||||
if (currentOverlayContext == null || currentContext == null) return;
|
||||
|
||||
final message = AppLocalizations.of(currentContext!).downloadMessageAsEMLFailed;
|
||||
appToast.showToastErrorMessage(currentOverlayContext!, message);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@ extension InitializeThreadDetailEmails on ThreadDetailController {
|
||||
properties: EmailUtils.getPropertiesForEmailGetMethod(
|
||||
session!,
|
||||
accountId!,
|
||||
),
|
||||
).union(additionalProperties),
|
||||
));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -26,7 +26,7 @@ extension LoadMoreThreadDetailEmails on ThreadDetailController {
|
||||
properties: EmailUtils.getPropertiesForEmailGetMethod(
|
||||
session!,
|
||||
accountId!,
|
||||
),
|
||||
).union(additionalProperties),
|
||||
));
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
|
||||
import 'package:model/email/mark_star_action.dart';
|
||||
import 'package:model/extensions/presentation_email_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_star_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_current_emails_flags_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||
|
||||
extension MarkCollapsedEmailStarSuccess on ThreadDetailController {
|
||||
void markCollapsedEmailStarSuccess(MarkAsStarEmailSuccess success) {
|
||||
final updatedMarkedEmail = emailIdsPresentation[success.emailId]
|
||||
?.updateKeywords({
|
||||
KeyWordIdentifier.emailFlagged: success.markStarAction == MarkStarAction.markStar,
|
||||
});
|
||||
if (updatedMarkedEmail == null) return;
|
||||
|
||||
if (mailboxDashBoardController.selectedEmail.value?.id == success.emailId) {
|
||||
mailboxDashBoardController.updateEmailFlagByEmailIds(
|
||||
[success.emailId],
|
||||
markStarAction: success.markStarAction,
|
||||
);
|
||||
}
|
||||
emailIdsPresentation[success.emailId] = updatedMarkedEmail;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import 'package:model/email/read_actions.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_current_emails_flags_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/close_thread_detail_action.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
extension MarkCollapsedEmailReadSuccess on ThreadDetailController {
|
||||
void markCollapsedEmailReadSuccess(MarkAsEmailReadSuccess success) {
|
||||
mailboxDashBoardController.updateEmailFlagByEmailIds(
|
||||
[success.emailId],
|
||||
readAction: success.readActions,
|
||||
);
|
||||
if (success.readActions == ReadActions.markAsUnread) {
|
||||
closeThreadDetailAction(currentContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import 'package:tmail_ui_user/features/manage_account/domain/state/create_new_rule_filter_state.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
extension QuickCreateRuleFromCollapsedEmailSuccess on ThreadDetailController {
|
||||
void quickCreateRuleFromCollapsedEmailSuccess(
|
||||
CreateNewRuleFilterSuccess success,
|
||||
) {
|
||||
if (success.newListRules.isEmpty ||
|
||||
currentContext == null ||
|
||||
currentOverlayContext == null) return;
|
||||
|
||||
appToast.showToastSuccessMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).newFilterWasCreated,
|
||||
);
|
||||
}
|
||||
}
|
||||
+376
@@ -0,0 +1,376 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:model/email/mark_star_action.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/email/read_actions.dart';
|
||||
import 'package:model/extensions/email_extension.dart';
|
||||
import 'package:model/extensions/session_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
extension ThreadDetailOnEmailActionClick on ThreadDetailController {
|
||||
void threadDetailOnEmailActionClick(
|
||||
PresentationEmail presentationEmail,
|
||||
EmailActionType emailActionType,
|
||||
) {
|
||||
switch(emailActionType) {
|
||||
case EmailActionType.markAsRead:
|
||||
_markRead(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.markAsUnread:
|
||||
_unRead(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.markAsStarred:
|
||||
_markStar(presentationEmail, MarkStarAction.markStar);
|
||||
break;
|
||||
case EmailActionType.unMarkAsStarred:
|
||||
_markStar(presentationEmail, MarkStarAction.unMarkStar);
|
||||
break;
|
||||
case EmailActionType.moveToMailbox:
|
||||
_moveEmail(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.moveToTrash:
|
||||
_trashEmail(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.deletePermanently:
|
||||
_deleteEmailPermanently(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.moveToSpam:
|
||||
_markEmailSpam(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.unSpam:
|
||||
_unSpamEmail(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.createRule:
|
||||
_quickCreateRule(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.unsubscribe:
|
||||
_unsubscribeEmail(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.archiveMessage:
|
||||
_archiveMessage(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.printAll:
|
||||
_printEmail(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.downloadMessageAsEML:
|
||||
_downloadMessageAsEML(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.editAsNewEmail:
|
||||
_editAsNewEmail(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.reply:
|
||||
_replyEmail(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.replyAll:
|
||||
_replyAll(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.replyToList:
|
||||
_replyToList(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.forward:
|
||||
_forward(presentationEmail);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _markRead(PresentationEmail presentationEmail) {
|
||||
if (session == null || accountId == null) return;
|
||||
|
||||
consumeState(emailActionReactor.markAsEmailRead(
|
||||
session!,
|
||||
accountId!,
|
||||
presentationEmail,
|
||||
readAction: ReadActions.markAsRead,
|
||||
));
|
||||
}
|
||||
|
||||
void _unRead(PresentationEmail presentationEmail) {
|
||||
if (session == null || accountId == null) return;
|
||||
|
||||
consumeState(emailActionReactor.markAsEmailRead(
|
||||
session!,
|
||||
accountId!,
|
||||
presentationEmail,
|
||||
readAction: ReadActions.markAsUnread,
|
||||
));
|
||||
}
|
||||
|
||||
void _markStar(
|
||||
PresentationEmail presentationEmail,
|
||||
MarkStarAction markStarAction,
|
||||
) {
|
||||
if (session == null || accountId == null) return;
|
||||
|
||||
consumeState(emailActionReactor.markAsStarEmail(
|
||||
session!,
|
||||
accountId!,
|
||||
presentationEmail,
|
||||
markStarAction: markStarAction,
|
||||
));
|
||||
}
|
||||
|
||||
Future<void> _moveEmail(PresentationEmail presentationEmail) async {
|
||||
if (session == null || accountId == null) return;
|
||||
|
||||
final moveActionRequest = await emailActionReactor.moveToMailbox(
|
||||
session!,
|
||||
accountId!,
|
||||
presentationEmail,
|
||||
mapMailbox: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: mailboxDashBoardController.selectedMailbox.value,
|
||||
isSearchEmailRunning: mailboxDashBoardController.searchController.isSearchEmailRunning,
|
||||
);
|
||||
|
||||
if (moveActionRequest == null) return;
|
||||
|
||||
mailboxDashBoardController.moveToMailbox(
|
||||
session!,
|
||||
accountId!,
|
||||
moveActionRequest.moveRequest,
|
||||
moveActionRequest.emailIdsWithReadStatus,
|
||||
);
|
||||
}
|
||||
|
||||
void _trashEmail(PresentationEmail presentationEmail) {
|
||||
if (session == null || accountId == null) return;
|
||||
|
||||
final moveActionRequest = emailActionReactor.moveToTrash(
|
||||
presentationEmail,
|
||||
mapMailbox: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: mailboxDashBoardController.selectedMailbox.value,
|
||||
isSearchEmailRunning: mailboxDashBoardController.searchController.isSearchEmailRunning,
|
||||
mapDefaultMailboxIdByRole: mailboxDashBoardController.mapDefaultMailboxIdByRole,
|
||||
);
|
||||
if (moveActionRequest == null) return;
|
||||
mailboxDashBoardController.moveToMailbox(
|
||||
session!,
|
||||
accountId!,
|
||||
moveActionRequest.moveRequest,
|
||||
moveActionRequest.emailIdsWithReadStatus,
|
||||
);
|
||||
}
|
||||
|
||||
void _markEmailSpam(PresentationEmail presentationEmail) {
|
||||
if (session == null || accountId == null) return;
|
||||
|
||||
final moveActionRequest = emailActionReactor.moveToSpam(
|
||||
presentationEmail,
|
||||
mapMailbox: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: mailboxDashBoardController.selectedMailbox.value,
|
||||
isSearchEmailRunning: mailboxDashBoardController.searchController.isSearchEmailRunning,
|
||||
mapDefaultMailboxIdByRole: mailboxDashBoardController.mapDefaultMailboxIdByRole,
|
||||
);
|
||||
if (moveActionRequest == null) return;
|
||||
mailboxDashBoardController.moveToMailbox(
|
||||
session!,
|
||||
accountId!,
|
||||
moveActionRequest.moveRequest,
|
||||
moveActionRequest.emailIdsWithReadStatus,
|
||||
);
|
||||
}
|
||||
|
||||
void _unSpamEmail(PresentationEmail presentationEmail) {
|
||||
if (session == null || accountId == null) return;
|
||||
|
||||
final moveActionRequest = emailActionReactor.unSpam(
|
||||
presentationEmail,
|
||||
mapMailbox: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: mailboxDashBoardController.selectedMailbox.value,
|
||||
isSearchEmailRunning: mailboxDashBoardController.searchController.isSearchEmailRunning,
|
||||
mapDefaultMailboxIdByRole: mailboxDashBoardController.mapDefaultMailboxIdByRole,
|
||||
);
|
||||
if (moveActionRequest == null) return;
|
||||
mailboxDashBoardController.moveToMailbox(
|
||||
session!,
|
||||
accountId!,
|
||||
moveActionRequest.moveRequest,
|
||||
moveActionRequest.emailIdsWithReadStatus,
|
||||
);
|
||||
}
|
||||
|
||||
void _deleteEmailPermanently(PresentationEmail email) {
|
||||
emailActionReactor.deleteEmailPermanently(
|
||||
email,
|
||||
onDeleteEmailRequest: (email) {
|
||||
popBack();
|
||||
mailboxDashBoardController.deleteEmailPermanently(email);
|
||||
},
|
||||
responsiveUtils: responsiveUtils,
|
||||
imagePaths: imagePaths,
|
||||
);
|
||||
}
|
||||
|
||||
void _quickCreateRule(PresentationEmail presentationEmail) {
|
||||
final emailAddress = presentationEmail.from?.first;
|
||||
if (session == null || accountId == null || emailAddress == null) return;
|
||||
|
||||
consumeState(emailActionReactor.quickCreateRule(
|
||||
session!,
|
||||
accountId!,
|
||||
emailAddress: emailAddress,
|
||||
));
|
||||
}
|
||||
|
||||
void _unsubscribeEmail(PresentationEmail presentationEmail) {
|
||||
emailActionReactor.unsubscribeEmail(
|
||||
presentationEmail,
|
||||
emailUnsubscribe: EmailUtils.parsingUnsubscribe(
|
||||
presentationEmail.listUnsubscribe ?? '',
|
||||
),
|
||||
onUnsubscribeByHttpsLink: mailboxDashBoardController.unsubscribeMail,
|
||||
onUnsubscribeByMailtoLink: (emailId, navigationRouter) {
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.fromUnsubscribeMailtoLink(
|
||||
listEmailAddress: navigationRouter.listEmailAddress,
|
||||
subject: navigationRouter.subject,
|
||||
body: navigationRouter.body,
|
||||
previousEmailId: emailId,
|
||||
)
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _archiveMessage(PresentationEmail presentationEmail) {
|
||||
if (currentContext == null) return;
|
||||
|
||||
emailActionReactor.archiveMessage(
|
||||
presentationEmail,
|
||||
onArchiveEmailRequest: (presentationEmail) {
|
||||
mailboxDashBoardController.archiveMessage(currentContext!, presentationEmail);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _printEmail(PresentationEmail presentationEmail) {
|
||||
consumeState(emailActionReactor.printEmail(
|
||||
presentationEmail,
|
||||
ownEmailAddress: mailboxDashBoardController.ownEmailAddress.value,
|
||||
emailLoaded: null,
|
||||
session: session,
|
||||
accountId: accountId,
|
||||
baseDownloadUrl: session?.getDownloadUrl(jmapUrl: dynamicUrlInterceptors.jmapUrl),
|
||||
transformConfiguration: TransformConfiguration.forPreviewEmailOnWeb(),
|
||||
onGetEmailContentFailure: _showUnknownErrorToast,
|
||||
));
|
||||
}
|
||||
|
||||
void _downloadMessageAsEML(PresentationEmail presentationEmail) {
|
||||
if (accountId == null || session == null) return;
|
||||
|
||||
consumeState(emailActionReactor.downloadMessageAsEML(
|
||||
session!,
|
||||
accountId!,
|
||||
presentationEmail,
|
||||
downloadProgressStateController: downloadProgressState,
|
||||
));
|
||||
}
|
||||
|
||||
void _editAsNewEmail(PresentationEmail presentationEmail) {
|
||||
if (accountId == null || session == null) return;
|
||||
|
||||
emailActionReactor.editAsNewEmail(
|
||||
presentationEmail,
|
||||
onEditAsEmailRequest: (presentationEmail) {
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.editAsNewEmail(presentationEmail),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _replyEmail(PresentationEmail presentationEmail) {
|
||||
emailActionReactor.replyEmail(
|
||||
presentationEmail,
|
||||
onReplyEmailRequest: (presentationEmail, emailLoaded) {
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.replyEmail(
|
||||
presentationEmail: presentationEmail,
|
||||
content: emailLoaded?.htmlContent,
|
||||
inlineImages: emailLoaded?.inlineImages,
|
||||
mailboxRole: presentationEmail.mailboxContain?.role,
|
||||
messageId: emailLoaded?.emailCurrent?.messageId,
|
||||
references: emailLoaded?.emailCurrent?.references,
|
||||
listPost: emailLoaded?.emailCurrent?.listPost,
|
||||
)
|
||||
);
|
||||
},
|
||||
emailLoaded: null,
|
||||
);
|
||||
}
|
||||
|
||||
void _replyAll(PresentationEmail presentationEmail) {
|
||||
emailActionReactor.replyAll(
|
||||
presentationEmail,
|
||||
onReplyAllRequest: (presentationEmail, emailLoaded) {
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.replyAllEmail(
|
||||
presentationEmail: presentationEmail,
|
||||
content: emailLoaded?.htmlContent,
|
||||
inlineImages: emailLoaded?.inlineImages,
|
||||
mailboxRole: presentationEmail.mailboxContain?.role,
|
||||
messageId: emailLoaded?.emailCurrent?.messageId,
|
||||
references: emailLoaded?.emailCurrent?.references,
|
||||
listPost: emailLoaded?.emailCurrent?.listPost,
|
||||
)
|
||||
);
|
||||
},
|
||||
emailLoaded: null,
|
||||
);
|
||||
}
|
||||
void _replyToList(PresentationEmail presentationEmail) {
|
||||
emailActionReactor.replyToList(
|
||||
presentationEmail,
|
||||
onReplyToListRequest: (presentationEmail, emailLoaded) {
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.replyToListEmail(
|
||||
presentationEmail: presentationEmail,
|
||||
content: emailLoaded?.htmlContent,
|
||||
inlineImages: emailLoaded?.inlineImages,
|
||||
mailboxRole: presentationEmail.mailboxContain?.role,
|
||||
messageId: emailLoaded?.emailCurrent?.messageId,
|
||||
references: emailLoaded?.emailCurrent?.references,
|
||||
listPost: emailLoaded?.emailCurrent?.listPost,
|
||||
)
|
||||
);
|
||||
},
|
||||
emailLoaded: null,
|
||||
);
|
||||
}
|
||||
void _forward(PresentationEmail presentationEmail) {
|
||||
emailActionReactor.forward(
|
||||
presentationEmail,
|
||||
onForwardRequest: (presentationEmail, emailLoaded) {
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.forwardEmail(
|
||||
presentationEmail: presentationEmail,
|
||||
content: emailLoaded?.htmlContent,
|
||||
attachments: emailLoaded?.attachments,
|
||||
inlineImages: emailLoaded?.inlineImages,
|
||||
messageId: emailLoaded?.emailCurrent?.messageId,
|
||||
references: emailLoaded?.emailCurrent?.references,
|
||||
)
|
||||
);
|
||||
},
|
||||
emailLoaded: null,
|
||||
);
|
||||
}
|
||||
|
||||
_showUnknownErrorToast() {
|
||||
if (currentOverlayContext != null && currentContext != null) {
|
||||
appToast.showToastErrorMessage(
|
||||
currentOverlayContext!,
|
||||
AppLocalizations.of(currentContext!).unknownError,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
extension ThreadDetailOpenEmailAddressDetailAction on ThreadDetailController {
|
||||
void openEmailAddressDetailAction(EmailAddress emailAddress) {
|
||||
if (session == null || accountId == null) return;
|
||||
|
||||
emailActionReactor.openEmailAddressDialog(
|
||||
session!,
|
||||
accountId!,
|
||||
emailAddress: emailAddress,
|
||||
responsiveUtils: responsiveUtils,
|
||||
imagePaths: imagePaths,
|
||||
appToast: appToast,
|
||||
onComposeEmailFromEmailAddressRequest: (emailAddress) {
|
||||
popBack();
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.fromEmailAddress(emailAddress),
|
||||
);
|
||||
},
|
||||
onQuickCreateRuleRequest: (quickCreateRuleStream) {
|
||||
consumeState(quickCreateRuleStream);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,11 @@ import 'package:core/data/model/source_type/data_source_type.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/http/http_client.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/print_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/data/data_source/thread_detail_data_source.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/data/data_source/thread_detail_remote_data_source_impl.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/data/network/thread_detail_api.dart';
|
||||
@@ -25,6 +30,11 @@ class ThreadDetailBindings extends BaseBindings {
|
||||
Get.put(ThreadDetailController(
|
||||
Get.find<GetThreadByIdInteractor>(),
|
||||
Get.find<GetEmailsByIdsInteractor>(),
|
||||
Get.find<MarkAsEmailReadInteractor>(),
|
||||
Get.find<MarkAsStarEmailInteractor>(),
|
||||
Get.find<PrintEmailInteractor>(),
|
||||
Get.find<GetEmailContentInteractor>(),
|
||||
Get.find<DownloadAttachmentForWebInteractor>(),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,43 +1,88 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/data/network/download/download_manager.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/individual_header_identifier.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/email/email_property.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/extensions/keyword_identifier_extension.dart';
|
||||
import 'package:model/extensions/session_extension.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_controller.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_star_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/print_email_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/domain/state/create_new_rule_filter_state.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/domain/usecases/create_new_email_rule_filter_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/search/email/presentation/search_email_controller.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_emails_by_ids_state.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_thread_by_id_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_emails_by_ids_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/action/thread_detail_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/close_thread_detail_action.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_email_ids_by_thread_id_success.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_emails_by_ids_success.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/initialize_thread_detail_emails.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_collapsed_email_download_states.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/mark_collapsed_email_star_success.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/mark_collapsed_email_unread_success.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/quick_create_rule_from_collapsed_email_success.dart';
|
||||
|
||||
class ThreadDetailController extends BaseController {
|
||||
final GetThreadByIdInteractor _getEmailIdsByThreadIdInteractor;
|
||||
final GetEmailsByIdsInteractor getEmailsByIdsInteractor;
|
||||
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
|
||||
final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
|
||||
final PrintEmailInteractor _printEmailInteractor;
|
||||
final GetEmailContentInteractor _getEmailContentInteractor;
|
||||
final DownloadAttachmentForWebInteractor _downloadAttachmentForWebInteractor;
|
||||
|
||||
ThreadDetailController(
|
||||
this._getEmailIdsByThreadIdInteractor,
|
||||
this.getEmailsByIdsInteractor,
|
||||
this._markAsEmailReadInteractor,
|
||||
this._markAsStarEmailInteractor,
|
||||
this._printEmailInteractor,
|
||||
this._getEmailContentInteractor,
|
||||
this._downloadAttachmentForWebInteractor,
|
||||
);
|
||||
|
||||
final emailIdsPresentation = <EmailId, PresentationEmail?>{}.obs;
|
||||
final currentExpandedEmailId = Rxn<EmailId>();
|
||||
final currentEmailLoaded = Rxn<EmailLoaded>();
|
||||
|
||||
late final EmailActionReactor emailActionReactor;
|
||||
final additionalProperties = Properties({
|
||||
IndividualHeaderIdentifier.listPostHeader.value,
|
||||
IndividualHeaderIdentifier.listUnsubscribeHeader.value,
|
||||
});
|
||||
|
||||
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
|
||||
final searchEmailController = Get.find<SearchEmailController>();
|
||||
final downloadManager = Get.find<DownloadManager>();
|
||||
final downloadProgressState = StreamController<Either<Failure, Success>>();
|
||||
|
||||
ScrollController? scrollController;
|
||||
CreateNewEmailRuleFilterInteractor? _createNewEmailRuleFilterInteractor;
|
||||
|
||||
AccountId? get accountId => mailboxDashBoardController.accountId.value;
|
||||
Session? get session => mailboxDashBoardController.sessionCurrent;
|
||||
@@ -67,6 +112,17 @@ class ThreadDetailController extends BaseController {
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
injectRuleFilterBindings(session, accountId);
|
||||
_createNewEmailRuleFilterInteractor = getBinding<CreateNewEmailRuleFilterInteractor>();
|
||||
emailActionReactor = EmailActionReactor(
|
||||
_markAsEmailReadInteractor,
|
||||
_markAsStarEmailInteractor,
|
||||
_createNewEmailRuleFilterInteractor,
|
||||
_printEmailInteractor,
|
||||
_getEmailContentInteractor,
|
||||
_downloadAttachmentForWebInteractor,
|
||||
);
|
||||
downloadProgressState.stream.listen(handleDownloadProgressState);
|
||||
ever(mailboxDashBoardController.selectedEmail, (presentationEmail) {
|
||||
if (presentationEmail?.threadId == null) {
|
||||
closeThreadDetailAction(currentContext);
|
||||
@@ -86,6 +142,22 @@ class ThreadDetailController extends BaseController {
|
||||
));
|
||||
}
|
||||
});
|
||||
ever(mailboxDashBoardController.threadDetailUIAction, (action) {
|
||||
if (action is UpdatedEmailKeywordsAction) {
|
||||
emailIdsPresentation
|
||||
[action.emailId]
|
||||
?.keywords
|
||||
?[action.updatedKeyword] = action.value;
|
||||
if (action.updatedKeyword == KeyWordIdentifierExtension.unsubscribeMail) {
|
||||
emailIdsPresentation
|
||||
[action.emailId]
|
||||
?..emailHeader?.removeWhere((element) {
|
||||
return element.name == EmailProperty.headerUnsubscribeKey;
|
||||
})
|
||||
..listUnsubscribeHeader?.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void reset() {
|
||||
@@ -103,6 +175,14 @@ class ThreadDetailController extends BaseController {
|
||||
initializeThreadDetailEmails();
|
||||
} else if (success is GetEmailsByIdsSuccess) {
|
||||
handleGetEmailsByIdsSuccess(success);
|
||||
} else if (success is MarkAsEmailReadSuccess) {
|
||||
markCollapsedEmailReadSuccess(success);
|
||||
} else if (success is MarkAsStarEmailSuccess) {
|
||||
markCollapsedEmailStarSuccess(success);
|
||||
} else if (success is CreateNewRuleFilterSuccess) {
|
||||
quickCreateRuleFromCollapsedEmailSuccess(success);
|
||||
} else if (success is DownloadAttachmentForWebSuccess) {
|
||||
handleDownloadSuccess(success);
|
||||
} else {
|
||||
super.handleSuccessViewState(success);
|
||||
}
|
||||
@@ -118,6 +198,10 @@ class ThreadDetailController extends BaseController {
|
||||
showRetryToast(failure);
|
||||
return;
|
||||
}
|
||||
if (failure is DownloadAttachmentForWebFailure) {
|
||||
handleDownloadFailure(failure);
|
||||
return;
|
||||
}
|
||||
super.handleFailureViewState(failure);
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,19 @@ import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/extensions/session_extension.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_bottom_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/get_mailbox_contain_extension.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/close_thread_detail_action.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/get_thread_detail_loading_view.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/get_thread_details_email_views.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/thread_detail_on_email_action_click.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/widgets/thread_detail_app_bar.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
class ThreadDetailView extends GetWidget<ThreadDetailController> {
|
||||
const ThreadDetailView({super.key});
|
||||
@@ -39,15 +40,29 @@ class ThreadDetailView extends GetWidget<ThreadDetailController> {
|
||||
lastEmailOfThread: controller.emailIdsPresentation.values.lastOrNull,
|
||||
ownUserName: controller.session?.getOwnEmailAddress() ?? '',
|
||||
mailboxContain: _getMailboxContain(),
|
||||
emailLoaded: getBinding<SingleEmailController>(
|
||||
tag: controller.emailIdsPresentation.keys.lastOrNull?.id.value
|
||||
)?.currentEmailLoaded.value,
|
||||
onEmailActionClick: (email, action) {
|
||||
// TODO: Next PR
|
||||
},
|
||||
onMoreActionClick: (p0, p1) {
|
||||
// TODO: Next PR
|
||||
},
|
||||
onEmailActionClick: controller.threadDetailOnEmailActionClick,
|
||||
onMoreActionClick: (presentationEmail, position) => controller.emailActionReactor.handleMoreEmailAction(
|
||||
mailboxContain: controller.mailboxDashBoardController.getMailboxContain(presentationEmail),
|
||||
presentationEmail: presentationEmail,
|
||||
position: position,
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
imagePaths: controller.imagePaths,
|
||||
username: controller.session?.username,
|
||||
handleEmailAction: controller.threadDetailOnEmailActionClick,
|
||||
additionalActions: [
|
||||
if (controller.responsiveUtils.isMobile(context)) ...[
|
||||
EmailActionType.forward,
|
||||
EmailActionType.replyAll,
|
||||
EmailActionType.replyToList,
|
||||
],
|
||||
EmailActionType.markAsStarred,
|
||||
EmailActionType.unMarkAsStarred,
|
||||
EmailActionType.moveToTrash,
|
||||
EmailActionType.deletePermanently,
|
||||
EmailActionType.printAll,
|
||||
EmailActionType.moveToMailbox,
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
Obx(() => controller.getThreadDetailLoadingView(
|
||||
|
||||
@@ -5,10 +5,8 @@ import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/extensions/email_extension.dart';
|
||||
import 'package:model/extensions/presentation_email_extension.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/styles/email_view_app_bar_widget_styles.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_app_bar_widget.dart';
|
||||
@@ -28,7 +26,6 @@ class ThreadDetailAppBar extends StatelessWidget {
|
||||
this.optionWidgets = const [],
|
||||
this.onEmailActionClick,
|
||||
this.onMoreActionClick,
|
||||
this.emailLoaded,
|
||||
});
|
||||
|
||||
final ResponsiveUtils responsiveUtils;
|
||||
@@ -41,16 +38,31 @@ class ThreadDetailAppBar extends StatelessWidget {
|
||||
final List<Widget> optionWidgets;
|
||||
final OnEmailActionClick? onEmailActionClick;
|
||||
final OnMoreActionClick? onMoreActionClick;
|
||||
final EmailLoaded? emailLoaded;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isReplyToListEnabled = EmailUtils.isReplyToListEnabled(
|
||||
emailLoaded?.emailCurrent?.listPost ?? '',
|
||||
lastEmailOfThread?.listPost ?? '',
|
||||
);
|
||||
|
||||
final child = LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
Widget backButton = EmailViewBackButton(
|
||||
imagePaths: imagePaths,
|
||||
onBackAction: () => closeThreadDetailAction(context),
|
||||
mailboxContain: mailboxContain,
|
||||
isSearchActivated: isSearchRunning,
|
||||
maxWidth: constraints.maxWidth,
|
||||
);
|
||||
if (responsiveUtils.isMobile(context)) {
|
||||
backButton = Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: backButton,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Container(
|
||||
height: PlatformInfo.isIOS
|
||||
? EmailViewAppBarWidgetStyles.heightIOS(context, responsiveUtils)
|
||||
@@ -76,20 +88,7 @@ class ThreadDetailAppBar extends StatelessWidget {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
if (_supportDisplayMailboxNameTitle(context))
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: EmailViewBackButton(
|
||||
imagePaths: imagePaths,
|
||||
onBackAction: () => closeThreadDetailAction(context),
|
||||
mailboxContain: mailboxContain,
|
||||
isSearchActivated: isSearchRunning,
|
||||
maxWidth: constraints.maxWidth,
|
||||
),
|
||||
),
|
||||
),
|
||||
...optionWidgets,
|
||||
if (_supportDisplayMailboxNameTitle(context)) backButton,
|
||||
if (lastEmailOfThread != null) ...[
|
||||
TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icReply,
|
||||
@@ -102,60 +101,45 @@ class ThreadDetailAppBar extends StatelessWidget {
|
||||
EmailActionType.reply,
|
||||
),
|
||||
),
|
||||
if (lastEmailOfThread!.getCountMailAddressWithoutMe(ownUserName) > 1)
|
||||
if (!responsiveUtils.isMobile(context)) ...[
|
||||
if (lastEmailOfThread!.getCountMailAddressWithoutMe(ownUserName) > 1)
|
||||
TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icReplyAll,
|
||||
iconSize: EmailViewAppBarWidgetStyles.buttonIconSize,
|
||||
iconColor: EmailViewAppBarWidgetStyles.iconColor,
|
||||
tooltipMessage: AppLocalizations.of(context).reply_all,
|
||||
backgroundColor: Colors.transparent,
|
||||
onTapActionCallback: () => onEmailActionClick?.call(
|
||||
lastEmailOfThread!,
|
||||
EmailActionType.replyAll,
|
||||
),
|
||||
),
|
||||
if (isReplyToListEnabled)
|
||||
TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icReply,
|
||||
iconSize: EmailViewAppBarWidgetStyles.buttonIconSize,
|
||||
iconColor: EmailViewAppBarWidgetStyles.iconColor,
|
||||
tooltipMessage: AppLocalizations.of(context).replyToList,
|
||||
backgroundColor: Colors.transparent,
|
||||
onTapActionCallback: () => onEmailActionClick?.call(
|
||||
lastEmailOfThread!,
|
||||
EmailActionType.replyToList,
|
||||
),
|
||||
),
|
||||
TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icReplyAll,
|
||||
icon: imagePaths.icForward,
|
||||
iconSize: EmailViewAppBarWidgetStyles.buttonIconSize,
|
||||
iconColor: EmailViewAppBarWidgetStyles.iconColor,
|
||||
tooltipMessage: AppLocalizations.of(context).reply_all,
|
||||
tooltipMessage: AppLocalizations.of(context).forward,
|
||||
backgroundColor: Colors.transparent,
|
||||
onTapActionCallback: () => onEmailActionClick?.call(
|
||||
lastEmailOfThread!,
|
||||
EmailActionType.replyAll,
|
||||
EmailActionType.forward,
|
||||
),
|
||||
),
|
||||
if (isReplyToListEnabled)
|
||||
TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icReply,
|
||||
iconSize: EmailViewAppBarWidgetStyles.buttonIconSize,
|
||||
iconColor: EmailViewAppBarWidgetStyles.iconColor,
|
||||
tooltipMessage: AppLocalizations.of(context).replyToList,
|
||||
backgroundColor: Colors.transparent,
|
||||
onTapActionCallback: () => onEmailActionClick?.call(
|
||||
lastEmailOfThread!,
|
||||
EmailActionType.replyToList,
|
||||
),
|
||||
),
|
||||
TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icForward,
|
||||
iconSize: EmailViewAppBarWidgetStyles.buttonIconSize,
|
||||
iconColor: EmailViewAppBarWidgetStyles.iconColor,
|
||||
tooltipMessage: AppLocalizations.of(context).forward,
|
||||
backgroundColor: Colors.transparent,
|
||||
onTapActionCallback: () => onEmailActionClick?.call(
|
||||
lastEmailOfThread!,
|
||||
EmailActionType.forward,
|
||||
),
|
||||
),
|
||||
TMailButtonWidget.fromIcon(
|
||||
icon: lastEmailOfThread!.hasStarred
|
||||
? imagePaths.icStar
|
||||
: imagePaths.icUnStar,
|
||||
iconSize: EmailViewAppBarWidgetStyles.buttonIconSize,
|
||||
iconColor: lastEmailOfThread!.hasStarred
|
||||
? null
|
||||
: EmailViewAppBarWidgetStyles.iconColor,
|
||||
backgroundColor: Colors.transparent,
|
||||
tooltipMessage: lastEmailOfThread!.hasStarred
|
||||
? AppLocalizations.of(context).not_starred
|
||||
: AppLocalizations.of(context).mark_as_starred,
|
||||
onTapActionCallback: () => onEmailActionClick?.call(
|
||||
lastEmailOfThread!,
|
||||
lastEmailOfThread!.hasStarred
|
||||
? EmailActionType.unMarkAsStarred
|
||||
: EmailActionType.markAsStarred
|
||||
),
|
||||
),
|
||||
],
|
||||
if (!responsiveUtils.isMobile(context)) const Spacer(),
|
||||
...optionWidgets,
|
||||
TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icMoreVertical,
|
||||
iconSize: EmailViewAppBarWidgetStyles.buttonIconSize,
|
||||
@@ -169,7 +153,7 @@ class ThreadDetailAppBar extends StatelessWidget {
|
||||
? (position) => onMoreActionClick?.call(lastEmailOfThread!, position)
|
||||
: null,
|
||||
),
|
||||
],
|
||||
] else const Spacer(),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -72,6 +72,7 @@ class ThreadDetailCollapsedEmail extends StatelessWidget {
|
||||
openEmailAddressDetailAction: openEmailAddressDetailAction,
|
||||
showRecipients: false,
|
||||
onTapAvatarActionClick: onToggleThreadDetailCollapseExpand,
|
||||
mailboxContain: mailboxContain,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
|
||||
Reference in New Issue
Block a user