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:
@@ -43,11 +43,9 @@ 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/state/button_state.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/exceptions/email_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/extensions/list_attachments_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/email_print.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/event_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/mark_read_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/move_action.dart';
|
||||
@@ -110,39 +108,35 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/email_unsubscribe.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_list/attachment_list_bottom_sheet_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_list/attachment_list_dialog_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_dialog_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/html_attachment_previewer.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/pdf_viewer/pdf_viewer.dart';
|
||||
import 'package:tmail_ui_user/features/email_previewer/email_previewer_dialog_view.dart';
|
||||
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/get_mailbox_contain_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/open_and_close_composer_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_current_emails_flags_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_routes.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/download/download_task_state.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_email_rule_filter_request.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/state/get_all_identities_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/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/rules_filter_creator/presentation/model/rules_filter_creator_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/search/email/presentation/search_email_controller.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/model/delete_action_type.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/focus_thread_detail_expanded_email.dart';
|
||||
import 'package:tmail_ui_user/features/thread_detail/presentation/thread_detail_controller.dart';
|
||||
import 'package:tmail_ui_user/main/error/capability_validator.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/localization_service.dart';
|
||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||
import 'package:tmail_ui_user/main/routes/dialog_router.dart';
|
||||
import 'package:tmail_ui_user/main/routes/navigation_router.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||
@@ -203,6 +197,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
Identity? _identitySelected;
|
||||
ButtonState? _printEmailButtonState;
|
||||
final obxListeners = <Worker>[];
|
||||
late final EmailActionReactor emailActionReactor;
|
||||
|
||||
final StreamController<Either<Failure, Success>> _downloadProgressStateController =
|
||||
StreamController<Either<Failure, Success>>.broadcast();
|
||||
@@ -254,6 +249,14 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
_injectCalendarEventBindings(session, accountId);
|
||||
_registerObxStreamListener();
|
||||
_listenDownloadAttachmentProgressState();
|
||||
emailActionReactor = EmailActionReactor(
|
||||
_markAsEmailReadInteractor,
|
||||
_markAsStarEmailInteractor,
|
||||
_createNewEmailRuleFilterInteractor,
|
||||
_printEmailInteractor,
|
||||
_getEmailContentInteractor,
|
||||
_downloadAttachmentForWebInteractor,
|
||||
);
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
@@ -408,6 +411,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
obxListeners.add(ever(mailboxDashBoardController.viewState, (viewState) {
|
||||
viewState.map((success) {
|
||||
if (success is UnsubscribeEmailSuccess) {
|
||||
if (success.emailId != _currentEmailId) return;
|
||||
emailUnsubscribe.value = null;
|
||||
}
|
||||
});
|
||||
@@ -766,13 +770,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
}
|
||||
|
||||
PresentationMailbox? getMailboxContain(PresentationEmail email) {
|
||||
if (mailboxDashBoardController.selectedMailbox.value == null) {
|
||||
return email.findMailboxContain(mailboxDashBoardController.mapMailboxById);
|
||||
} else {
|
||||
return mailboxDashBoardController.searchController.isSearchEmailRunning
|
||||
? email.findMailboxContain(mailboxDashBoardController.mapMailboxById)
|
||||
: mailboxDashBoardController.selectedMailbox.value;
|
||||
}
|
||||
return mailboxDashBoardController.getMailboxContain(email);
|
||||
}
|
||||
|
||||
void markAsEmailRead(
|
||||
@@ -1200,81 +1198,28 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
}
|
||||
|
||||
void moveToMailbox(BuildContext context, PresentationEmail email) async {
|
||||
final currentMailbox = getMailboxContain(email);
|
||||
|
||||
if (currentMailbox != null && accountId != null) {
|
||||
final arguments = DestinationPickerArguments(
|
||||
if (session != null && accountId != null) {
|
||||
final moveActionRequest = await emailActionReactor.moveToMailbox(
|
||||
session!,
|
||||
accountId!,
|
||||
MailboxActions.moveEmail,
|
||||
session,
|
||||
mailboxIdSelected: currentMailbox.mailboxId
|
||||
email,
|
||||
mapMailbox: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: mailboxDashBoardController.selectedMailbox.value,
|
||||
isSearchEmailRunning: mailboxDashBoardController.searchController.isSearchEmailRunning,
|
||||
);
|
||||
|
||||
final destinationMailbox = PlatformInfo.isWeb
|
||||
? await DialogRouter.pushGeneralDialog(routeName: AppRoutes.destinationPicker, arguments: arguments)
|
||||
: await push(AppRoutes.destinationPicker, arguments: arguments);
|
||||
|
||||
if (destinationMailbox != null &&
|
||||
destinationMailbox is PresentationMailbox &&
|
||||
session != null &&
|
||||
context.mounted
|
||||
) {
|
||||
_dispatchMoveToAction(
|
||||
context,
|
||||
accountId!,
|
||||
session!,
|
||||
email,
|
||||
currentMailbox,
|
||||
destinationMailbox);
|
||||
if (!context.mounted || moveActionRequest == null) return;
|
||||
mailboxDashBoardController.moveToMailbox(
|
||||
session!,
|
||||
accountId!,
|
||||
moveActionRequest.moveRequest,
|
||||
moveActionRequest.emailIdsWithReadStatus,
|
||||
);
|
||||
if (_threadDetailController?.emailIdsPresentation.length == 1) {
|
||||
_threadDetailController?.closeThreadDetailAction(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _dispatchMoveToAction(
|
||||
BuildContext context,
|
||||
AccountId accountId,
|
||||
Session session,
|
||||
PresentationEmail emailSelected,
|
||||
PresentationMailbox currentMailbox,
|
||||
PresentationMailbox destinationMailbox
|
||||
) {
|
||||
if (destinationMailbox.isTrash) {
|
||||
_moveToTrashAction(
|
||||
context,
|
||||
session,
|
||||
accountId,
|
||||
MoveToMailboxRequest(
|
||||
{currentMailbox.id: [emailSelected.id!]},
|
||||
destinationMailbox.id,
|
||||
MoveAction.moving,
|
||||
EmailActionType.moveToTrash),
|
||||
{emailSelected.id!: emailSelected.hasRead});
|
||||
} else if (destinationMailbox.isSpam) {
|
||||
_moveToSpamAction(
|
||||
context,
|
||||
session,
|
||||
accountId,
|
||||
MoveToMailboxRequest(
|
||||
{currentMailbox.id: [emailSelected.id!]},
|
||||
destinationMailbox.id,
|
||||
MoveAction.moving,
|
||||
EmailActionType.moveToSpam),
|
||||
{emailSelected.id!: emailSelected.hasRead});
|
||||
} else {
|
||||
_moveToMailbox(
|
||||
context,
|
||||
session,
|
||||
accountId,
|
||||
MoveToMailboxRequest(
|
||||
{currentMailbox.id: [emailSelected.id!]},
|
||||
destinationMailbox.id,
|
||||
MoveAction.moving,
|
||||
EmailActionType.moveToMailbox,
|
||||
destinationPath: destinationMailbox.mailboxPath),
|
||||
{emailSelected.id!: emailSelected.hasRead});
|
||||
}
|
||||
}
|
||||
|
||||
void _moveToMailbox(
|
||||
BuildContext context,
|
||||
Session session,
|
||||
@@ -1282,7 +1227,6 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
MoveToMailboxRequest moveRequest,
|
||||
Map<EmailId, bool> emailIdsWithReadStatus,
|
||||
) {
|
||||
closeEmailView(context: context);
|
||||
consumeState(_moveToMailboxInteractor.execute(
|
||||
session,
|
||||
accountId,
|
||||
@@ -1332,94 +1276,71 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
}
|
||||
|
||||
void moveToTrash(BuildContext context, PresentationEmail email) {
|
||||
final trashMailboxId = mailboxDashBoardController.getMailboxIdByRole(PresentationMailbox.roleTrash);
|
||||
final currentMailbox = getMailboxContain(email);
|
||||
|
||||
if (session != null && accountId != null && currentMailbox != null && trashMailboxId != null) {
|
||||
_moveToTrashAction(
|
||||
context,
|
||||
if (session != null && accountId != null) {
|
||||
final moveActionRequest = emailActionReactor.moveToTrash(
|
||||
email,
|
||||
mapMailbox: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: mailboxDashBoardController.selectedMailbox.value,
|
||||
isSearchEmailRunning: mailboxDashBoardController.searchController.isSearchEmailRunning,
|
||||
mapDefaultMailboxIdByRole: mailboxDashBoardController.mapDefaultMailboxIdByRole,
|
||||
);
|
||||
if (!context.mounted || moveActionRequest == null) return;
|
||||
mailboxDashBoardController.moveToMailbox(
|
||||
session!,
|
||||
accountId!,
|
||||
MoveToMailboxRequest(
|
||||
{currentMailbox.id: [email.id!]},
|
||||
trashMailboxId,
|
||||
MoveAction.moving,
|
||||
EmailActionType.moveToTrash),
|
||||
{email.id!: email.hasRead},
|
||||
moveActionRequest.moveRequest,
|
||||
moveActionRequest.emailIdsWithReadStatus,
|
||||
);
|
||||
if (_threadDetailController?.emailIdsPresentation.length == 1) {
|
||||
_threadDetailController?.closeThreadDetailAction(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _moveToTrashAction(
|
||||
BuildContext context,
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
MoveToMailboxRequest moveRequest,
|
||||
Map<EmailId, bool> emailIdsWithReadStatus,
|
||||
) {
|
||||
closeEmailView(context: context);
|
||||
mailboxDashBoardController.moveToMailbox(
|
||||
session,
|
||||
accountId,
|
||||
moveRequest,
|
||||
emailIdsWithReadStatus,
|
||||
);
|
||||
}
|
||||
|
||||
void moveToSpam(BuildContext context, PresentationEmail email) {
|
||||
final spamMailboxId = mailboxDashBoardController.spamMailboxId;
|
||||
final currentMailbox = getMailboxContain(email);
|
||||
|
||||
if (session != null && accountId != null && currentMailbox != null && spamMailboxId != null) {
|
||||
_moveToSpamAction(
|
||||
context,
|
||||
if (session != null && accountId != null) {
|
||||
final moveActionRequest = emailActionReactor.moveToSpam(
|
||||
email,
|
||||
mapMailbox: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: mailboxDashBoardController.selectedMailbox.value,
|
||||
isSearchEmailRunning: mailboxDashBoardController.searchController.isSearchEmailRunning,
|
||||
mapDefaultMailboxIdByRole: mailboxDashBoardController.mapDefaultMailboxIdByRole,
|
||||
);
|
||||
if (!context.mounted || moveActionRequest == null) return;
|
||||
mailboxDashBoardController.moveToMailbox(
|
||||
session!,
|
||||
accountId!,
|
||||
MoveToMailboxRequest(
|
||||
{currentMailbox.id: [email.id!]},
|
||||
spamMailboxId,
|
||||
MoveAction.moving,
|
||||
EmailActionType.moveToSpam),
|
||||
{email.id!: email.hasRead},
|
||||
moveActionRequest.moveRequest,
|
||||
moveActionRequest.emailIdsWithReadStatus,
|
||||
);
|
||||
if (_threadDetailController?.emailIdsPresentation.length == 1) {
|
||||
_threadDetailController?.closeThreadDetailAction(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unSpam(BuildContext context, PresentationEmail email) {
|
||||
final spamMailboxId = mailboxDashBoardController.spamMailboxId;
|
||||
final inboxMailboxId = mailboxDashBoardController.getMailboxIdByRole(PresentationMailbox.roleInbox);
|
||||
|
||||
if (session != null && accountId != null && spamMailboxId != null && inboxMailboxId != null) {
|
||||
_moveToSpamAction(
|
||||
context,
|
||||
if (session != null && accountId != null) {
|
||||
final moveActionRequest = emailActionReactor.unSpam(
|
||||
email,
|
||||
mapMailbox: mailboxDashBoardController.mapMailboxById,
|
||||
selectedMailbox: mailboxDashBoardController.selectedMailbox.value,
|
||||
isSearchEmailRunning: mailboxDashBoardController.searchController.isSearchEmailRunning,
|
||||
mapDefaultMailboxIdByRole: mailboxDashBoardController.mapDefaultMailboxIdByRole,
|
||||
);
|
||||
if (!context.mounted || moveActionRequest == null) return;
|
||||
mailboxDashBoardController.moveToMailbox(
|
||||
session!,
|
||||
accountId!,
|
||||
MoveToMailboxRequest(
|
||||
{spamMailboxId: [email.id!]},
|
||||
inboxMailboxId,
|
||||
MoveAction.moving,
|
||||
EmailActionType.unSpam),
|
||||
{email.id!: email.hasRead},
|
||||
moveActionRequest.moveRequest,
|
||||
moveActionRequest.emailIdsWithReadStatus,
|
||||
);
|
||||
if (_threadDetailController?.emailIdsPresentation.length == 1) {
|
||||
_threadDetailController?.closeThreadDetailAction(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _moveToSpamAction(
|
||||
BuildContext context,
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
MoveToMailboxRequest moveRequest,
|
||||
Map<EmailId, bool> emailIdsWithReadStatus,
|
||||
) {
|
||||
closeEmailView(context: context);
|
||||
mailboxDashBoardController.moveToMailbox(
|
||||
session,
|
||||
accountId,
|
||||
moveRequest,
|
||||
emailIdsWithReadStatus,
|
||||
);
|
||||
}
|
||||
|
||||
void markAsStarEmail(
|
||||
PresentationEmail presentationEmail,
|
||||
MarkStarAction markStarAction,
|
||||
@@ -1451,13 +1372,34 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
void handleEmailAction(BuildContext context, PresentationEmail presentationEmail, EmailActionType actionType) {
|
||||
switch(actionType) {
|
||||
case EmailActionType.markAsUnread:
|
||||
markAsEmailRead(presentationEmail, ReadActions.markAsUnread, MarkReadAction.tap);
|
||||
if (session != null && accountId != null) {
|
||||
consumeState(emailActionReactor.markAsEmailRead(
|
||||
session!,
|
||||
accountId!,
|
||||
presentationEmail,
|
||||
readAction: ReadActions.markAsUnread,
|
||||
));
|
||||
}
|
||||
break;
|
||||
case EmailActionType.markAsStarred:
|
||||
markAsStarEmail(presentationEmail, MarkStarAction.markStar);
|
||||
if (session != null && accountId != null) {
|
||||
consumeState(emailActionReactor.markAsStarEmail(
|
||||
session!,
|
||||
accountId!,
|
||||
presentationEmail,
|
||||
markStarAction: MarkStarAction.markStar,
|
||||
));
|
||||
}
|
||||
break;
|
||||
case EmailActionType.unMarkAsStarred:
|
||||
markAsStarEmail(presentationEmail, MarkStarAction.unMarkStar);
|
||||
if (session != null && accountId != null) {
|
||||
consumeState(emailActionReactor.markAsStarEmail(
|
||||
session!,
|
||||
accountId!,
|
||||
presentationEmail,
|
||||
markStarAction: MarkStarAction.unMarkStar,
|
||||
));
|
||||
}
|
||||
break;
|
||||
case EmailActionType.moveToMailbox:
|
||||
moveToMailbox(context, presentationEmail);
|
||||
@@ -1495,69 +1437,38 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
case EmailActionType.reply:
|
||||
_replyEmail(presentationEmail);
|
||||
break;
|
||||
case EmailActionType.replyAll:
|
||||
case EmailActionType.replyToList:
|
||||
case EmailActionType.forward:
|
||||
pressEmailAction(actionType, presentationEmail);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void openEmailAddressDialog(BuildContext context, EmailAddress emailAddress) {
|
||||
if (responsiveUtils.isScreenWithShortestSide(context)) {
|
||||
Get.bottomSheet(
|
||||
PointerInterceptor(
|
||||
child: EmailAddressBottomSheetBuilder(
|
||||
imagePaths: imagePaths,
|
||||
emailAddress: emailAddress,
|
||||
onCloseDialogAction: popBack,
|
||||
onCopyEmailAddressAction: (emailAddress) =>
|
||||
copyEmailAddress(context, emailAddress),
|
||||
onComposeEmailAction: composeEmailFromEmailAddress,
|
||||
onQuickCreatingRuleEmailDialogAction: (emailAddress) =>
|
||||
quickCreatingRule(context, emailAddress),
|
||||
),
|
||||
),
|
||||
useRootNavigator: true,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadiusDirectional.only(
|
||||
topStart: Radius.circular(16.0),
|
||||
topEnd: Radius.circular(16.0),
|
||||
),
|
||||
),
|
||||
isScrollControlled: true,
|
||||
enableDrag: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
} else {
|
||||
Get.dialog(
|
||||
PointerInterceptor(
|
||||
child: EmailAddressDialogBuilder(
|
||||
imagePaths: imagePaths,
|
||||
emailAddress: emailAddress,
|
||||
onCloseDialogAction: popBack,
|
||||
onCopyEmailAddressAction: (emailAddress) =>
|
||||
copyEmailAddress(context, emailAddress),
|
||||
onComposeEmailAction: composeEmailFromEmailAddress,
|
||||
onQuickCreatingRuleEmailDialogAction: (emailAddress) =>
|
||||
quickCreatingRule(context, emailAddress),
|
||||
),
|
||||
),
|
||||
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
||||
);
|
||||
}
|
||||
}
|
||||
void openEmailAddressDialog(EmailAddress emailAddress) {
|
||||
if (session == null || accountId == null) return;
|
||||
|
||||
void copyEmailAddress(BuildContext context, EmailAddress emailAddress) {
|
||||
Clipboard.setData(ClipboardData(text: emailAddress.emailAddress));
|
||||
appToast.showToastSuccessMessage(
|
||||
context,
|
||||
AppLocalizations.of(context).email_address_copied_to_clipboard,
|
||||
emailActionReactor.openEmailAddressDialog(
|
||||
session!,
|
||||
accountId!,
|
||||
emailAddress: emailAddress,
|
||||
responsiveUtils: responsiveUtils,
|
||||
imagePaths: imagePaths,
|
||||
appToast: appToast,
|
||||
onComposeEmailFromEmailAddressRequest: (emailAddress) {
|
||||
popBack();
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.fromEmailAddress(emailAddress),
|
||||
);
|
||||
},
|
||||
onQuickCreateRuleRequest: (quickCreateRuleStream) {
|
||||
consumeState(quickCreateRuleStream);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void composeEmailFromEmailAddress(EmailAddress emailAddress) {
|
||||
popBack();
|
||||
mailboxDashBoardController.openComposer(ComposerArguments.fromEmailAddress(emailAddress));
|
||||
}
|
||||
|
||||
Future<void> openMailToLink(Uri? uri) async {
|
||||
if (uri == null) return;
|
||||
|
||||
@@ -1577,34 +1488,18 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
}
|
||||
|
||||
void deleteEmailPermanently(BuildContext context, PresentationEmail email) {
|
||||
if (responsiveUtils.isMobile(context)) {
|
||||
(ConfirmationDialogActionSheetBuilder(context)
|
||||
..messageText(DeleteActionType.single.getContentDialog(context))
|
||||
..onCancelAction(AppLocalizations.of(context).cancel, () => popBack())
|
||||
..onConfirmAction(DeleteActionType.single.getConfirmActionName(context), () => _deleteEmailPermanentlyAction(context, email)))
|
||||
.show();
|
||||
} else {
|
||||
Get.dialog(
|
||||
PointerInterceptor(child: ConfirmationDialogBuilder(
|
||||
key: const Key('confirm_dialog_delete_email_permanently'),
|
||||
imagePath: imagePaths,
|
||||
title: DeleteActionType.single.getTitleDialog(context),
|
||||
textContent: DeleteActionType.single.getContentDialog(context),
|
||||
confirmText: DeleteActionType.single.getConfirmActionName(context),
|
||||
cancelText: AppLocalizations.of(context).cancel,
|
||||
onConfirmButtonAction: () => _deleteEmailPermanentlyAction(context, email),
|
||||
onCancelButtonAction: popBack,
|
||||
onCloseButtonAction: popBack,
|
||||
)),
|
||||
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _deleteEmailPermanentlyAction(BuildContext context, PresentationEmail email) {
|
||||
popBack();
|
||||
closeEmailView(context: context);
|
||||
mailboxDashBoardController.deleteEmailPermanently(email);
|
||||
emailActionReactor.deleteEmailPermanently(
|
||||
email,
|
||||
onDeleteEmailRequest: (email) {
|
||||
popBack();
|
||||
mailboxDashBoardController.deleteEmailPermanently(email);
|
||||
if (_threadDetailController?.emailIdsPresentation.length == 1) {
|
||||
_threadDetailController?.closeThreadDetailAction(context);
|
||||
}
|
||||
},
|
||||
responsiveUtils: responsiveUtils,
|
||||
imagePaths: imagePaths,
|
||||
);
|
||||
}
|
||||
|
||||
void _handleSendReceiptToSenderAction(BuildContext context) {
|
||||
@@ -1793,32 +1688,11 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
popBack();
|
||||
|
||||
if (accountId != null && session != null) {
|
||||
final arguments = RulesFilterCreatorArguments(
|
||||
accountId!,
|
||||
consumeState(emailActionReactor.quickCreateRule(
|
||||
session!,
|
||||
emailAddress: emailAddress);
|
||||
|
||||
final newRuleFilterRequest = PlatformInfo.isWeb
|
||||
? await DialogRouter.pushGeneralDialog(routeName: AppRoutes.rulesFilterCreator, arguments: arguments)
|
||||
: await push(AppRoutes.rulesFilterCreator, arguments: arguments);
|
||||
|
||||
if (newRuleFilterRequest is CreateNewEmailRuleFilterRequest) {
|
||||
_createNewRuleFilterAction(accountId!, newRuleFilterRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _createNewRuleFilterAction(
|
||||
AccountId accountId,
|
||||
CreateNewEmailRuleFilterRequest ruleFilterRequest
|
||||
) async {
|
||||
try {
|
||||
_createNewEmailRuleFilterInteractor = Get.find<CreateNewEmailRuleFilterInteractor>();
|
||||
} catch (e) {
|
||||
logError('SingleEmailController::onInit(): ${e.toString()}');
|
||||
}
|
||||
if (_createNewEmailRuleFilterInteractor != null) {
|
||||
consumeState(_createNewEmailRuleFilterInteractor!.execute(accountId, ruleFilterRequest));
|
||||
accountId!,
|
||||
emailAddress: emailAddress,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1929,70 +1803,30 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
}
|
||||
|
||||
void _unsubscribeEmail(BuildContext context, PresentationEmail presentationEmail) {
|
||||
showConfirmDialogAction(
|
||||
context,
|
||||
'',
|
||||
AppLocalizations.of(context).unsubscribe,
|
||||
onConfirmAction: () {
|
||||
if (emailUnsubscribe.value?.httpLinks.isNotEmpty == true) {
|
||||
_handleUnsubscribeMailByHttpsLink(
|
||||
context: context,
|
||||
emailId: presentationEmail.id!,
|
||||
httpLinks: emailUnsubscribe.value!.httpLinks
|
||||
);
|
||||
} else if (emailUnsubscribe.value?.mailtoLinks.isNotEmpty == true) {
|
||||
_handleUnsubscribeMailByMailtoLink(
|
||||
context: context,
|
||||
emailId: presentationEmail.id!,
|
||||
mailtoLinks: emailUnsubscribe.value!.mailtoLinks
|
||||
);
|
||||
}
|
||||
emailActionReactor.unsubscribeEmail(
|
||||
presentationEmail,
|
||||
emailUnsubscribe: emailUnsubscribe.value,
|
||||
onUnsubscribeByHttpsLink: mailboxDashBoardController.unsubscribeMail,
|
||||
onUnsubscribeByMailtoLink: (emailId, navigationRouter) {
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.fromUnsubscribeMailtoLink(
|
||||
listEmailAddress: navigationRouter.listEmailAddress,
|
||||
subject: navigationRouter.subject,
|
||||
body: navigationRouter.body,
|
||||
previousEmailId: emailId,
|
||||
)
|
||||
);
|
||||
},
|
||||
showAsBottomSheet: true,
|
||||
dialogMargin: MediaQuery.paddingOf(context).add(const EdgeInsets.only(bottom: 12)),
|
||||
title: AppLocalizations.of(context).unsubscribeMail,
|
||||
listTextSpan: [
|
||||
TextSpan(text: AppLocalizations.of(context).unsubscribeMailDialogMessage),
|
||||
TextSpan(
|
||||
text: ' ${presentationEmail.getSenderName()}',
|
||||
style: ThemeUtils.textStyleM3BodyMedium1.copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
const TextSpan(text: ' ?'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
void _handleUnsubscribeMailByHttpsLink({
|
||||
required BuildContext context,
|
||||
required EmailId emailId,
|
||||
required List<String> httpLinks
|
||||
}) {
|
||||
log('SingleEmailController::_handleUnsubscribeMailByHttpsLink:httpLinks: $httpLinks');
|
||||
mailboxDashBoardController.unsubscribeMail(emailId);
|
||||
AppUtils.launchLink(httpLinks.first);
|
||||
}
|
||||
|
||||
void _handleUnsubscribeMailByMailtoLink({
|
||||
required BuildContext context,
|
||||
required EmailId emailId,
|
||||
required List<String> mailtoLinks
|
||||
}) {
|
||||
log('SingleEmailController::_handleUnsubscribeMailByMailtoLink:mailtoLinks: $mailtoLinks');
|
||||
final navigationRouter = RouteUtils.generateNavigationRouterFromMailtoLink(mailtoLinks.first);
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.fromUnsubscribeMailtoLink(
|
||||
listEmailAddress: navigationRouter.listEmailAddress,
|
||||
subject: navigationRouter.subject,
|
||||
body: navigationRouter.body,
|
||||
previousEmailId: emailId,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void archiveMessage(BuildContext context, PresentationEmail email) {
|
||||
mailboxDashBoardController.archiveMessage(context, email);
|
||||
emailActionReactor.archiveMessage(
|
||||
email,
|
||||
onArchiveEmailRequest: (presentationEmail) {
|
||||
mailboxDashBoardController.archiveMessage(context, presentationEmail);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _printEmail(BuildContext context, PresentationEmail email) {
|
||||
@@ -2003,40 +1837,11 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
|
||||
_printEmailButtonState = ButtonState.disabled;
|
||||
|
||||
final locale = Localizations.localeOf(context);
|
||||
final appLocalizations = AppLocalizations.of(context);
|
||||
|
||||
consumeState(
|
||||
_printEmailInteractor.execute(
|
||||
EmailPrint(
|
||||
appName: appLocalizations.app_name,
|
||||
userName: mailboxDashBoardController.ownEmailAddress.value,
|
||||
attachments: currentEmailLoaded.value!.attachments,
|
||||
emailContent: currentEmailLoaded.value!.htmlContent,
|
||||
fromPrefix: appLocalizations.from_email_address_prefix,
|
||||
toPrefix: appLocalizations.to_email_address_prefix,
|
||||
ccPrefix: appLocalizations.cc_email_address_prefix,
|
||||
bccPrefix: appLocalizations.bcc_email_address_prefix,
|
||||
replyToPrefix: appLocalizations.replyToEmailAddressPrefix,
|
||||
titleAttachment: appLocalizations.attachments.toLowerCase(),
|
||||
toAddress: email.to?.listEmailAddressToString(isFullEmailAddress: true),
|
||||
ccAddress: email.cc?.listEmailAddressToString(isFullEmailAddress: true),
|
||||
bccAddress: email.bcc?.listEmailAddressToString(isFullEmailAddress: true),
|
||||
replyToAddress: email.replyTo?.listEmailAddressToString(isFullEmailAddress: true),
|
||||
sender: email.from?.isNotEmpty == true
|
||||
? email.from!.first
|
||||
: null,
|
||||
receiveTime: email.getReceivedAt(
|
||||
locale.toLanguageTag(),
|
||||
pattern: email.receivedAt
|
||||
?.value
|
||||
.toLocal()
|
||||
.toPatternForPrinting(locale.toLanguageTag()),
|
||||
),
|
||||
subject: email.subject,
|
||||
)
|
||||
)
|
||||
);
|
||||
consumeState(emailActionReactor.printEmail(
|
||||
email,
|
||||
ownEmailAddress: mailboxDashBoardController.ownEmailAddress.value,
|
||||
emailLoaded: currentEmailLoaded.value!,
|
||||
));
|
||||
}
|
||||
|
||||
void _showMessageWhenStartingEmailPrinting() {
|
||||
@@ -2181,34 +1986,46 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
}
|
||||
|
||||
void _downloadMessageAsEML(PresentationEmail presentationEmail) {
|
||||
final emlAttachment = presentationEmail.createEMLAttachment();
|
||||
if (emlAttachment.blobId == null) {
|
||||
consumeState(Stream.value(Left(DownloadAttachmentForWebFailure(exception: NotFoundEmailBlobIdException()))));
|
||||
return;
|
||||
}
|
||||
if (accountId == null || session == null) return;
|
||||
|
||||
downloadAttachmentForWeb(emlAttachment);
|
||||
consumeState(emailActionReactor.downloadMessageAsEML(
|
||||
session!,
|
||||
accountId!,
|
||||
presentationEmail,
|
||||
downloadProgressStateController: _downloadProgressStateController,
|
||||
));
|
||||
}
|
||||
|
||||
void _editAsNewEmail(PresentationEmail presentationEmail) {
|
||||
if (accountId == null || session == null) return;
|
||||
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.editAsNewEmail(presentationEmail),
|
||||
emailActionReactor.editAsNewEmail(
|
||||
presentationEmail,
|
||||
onEditAsEmailRequest: (presentationEmail) {
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.editAsNewEmail(presentationEmail),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _replyEmail(PresentationEmail presentationEmail) {
|
||||
mailboxDashBoardController.openComposer(
|
||||
ComposerArguments.replyEmail(
|
||||
presentationEmail: presentationEmail,
|
||||
content: currentEmailLoaded.value?.htmlContent ?? '',
|
||||
inlineImages: currentEmailLoaded.value?.inlineImages ?? [],
|
||||
mailboxRole: presentationEmail.mailboxContain?.role,
|
||||
messageId: currentEmailLoaded.value?.emailCurrent?.messageId,
|
||||
references: currentEmailLoaded.value?.emailCurrent?.references,
|
||||
listPost: currentEmailLoaded.value?.emailCurrent?.listPost,
|
||||
)
|
||||
emailActionReactor.replyEmail(
|
||||
presentationEmail,
|
||||
emailLoaded: currentEmailLoaded.value,
|
||||
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,
|
||||
)
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,22 +11,15 @@ import 'package:jmap_dart_client/jmap/mail/calendar/calendar_event.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.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/list_email_address_extension.dart';
|
||||
import 'package:model/extensions/presentation_email_extension.dart';
|
||||
import 'package:model/extensions/presentation_mailbox_extension.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/optional_expanded.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/optional_scroll.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/popup_menu/popup_menu_item_action_widget.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_event_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/context_item_email_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/popup_menu_item_email_action.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/styles/email_view_styles.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_event_action_banner_widget.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_event_detail_widget.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart';
|
||||
@@ -39,12 +32,10 @@ import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_loa
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/information_sender_and_receiver_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/mail_unsubscribed_banner.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/view_entire_message_with_message_clipped_widget.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_open_context_menu_extension.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/verify_display_overlay_view_on_iframe_extension.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/vacation_response_extension.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
||||
|
||||
class EmailView extends GetWidget<SingleEmailController> {
|
||||
@@ -97,11 +88,15 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
isSearchActivated: controller.mailboxDashBoardController.searchController.isSearchEmailRunning,
|
||||
onBackAction: () => controller.closeEmailView(context: context),
|
||||
onEmailActionClick: (email, action) => controller.handleEmailAction(context, email, action),
|
||||
onMoreActionClick: (presentationEmail, position) => _handleMoreEmailAction(
|
||||
context: context,
|
||||
onMoreActionClick: (presentationEmail, position) => controller.emailActionReactor.handleMoreEmailAction(
|
||||
mailboxContain: controller.getMailboxContain(presentationEmail),
|
||||
presentationEmail: presentationEmail,
|
||||
position: position,
|
||||
emailLoaded: controller.currentEmailLoaded.value,
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
imagePaths: controller.imagePaths,
|
||||
username: controller.session?.username,
|
||||
handleEmailAction: (email, action) => controller.handleEmailAction(context, email, action),
|
||||
additionalActions: [],
|
||||
),
|
||||
supportBackAction: !isInsideThreadDetailView,
|
||||
appBarDecoration: isInsideThreadDetailView
|
||||
@@ -278,18 +273,38 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
sMimeStatus: controller.currentEmailLoaded.value?.sMimeStatus,
|
||||
emailUnsubscribe: controller.emailUnsubscribe.value,
|
||||
maxBodyHeight: maxBodyHeight,
|
||||
openEmailAddressDetailAction: controller.openEmailAddressDialog,
|
||||
openEmailAddressDetailAction: (_, emailAddress) => controller.openEmailAddressDialog(emailAddress),
|
||||
onEmailActionClick: (presentationEmail, actionType) => controller.handleEmailAction(context, presentationEmail, actionType),
|
||||
isInsideThreadDetailView: isInsideThreadDetailView,
|
||||
emailLoaded: controller.currentEmailLoaded.value,
|
||||
onMoreActionClick: (email, position) => _handleMoreEmailAction(
|
||||
context: context,
|
||||
presentationEmail: email,
|
||||
onMoreActionClick: (presentationEmail, position) => controller.emailActionReactor.handleMoreEmailAction(
|
||||
mailboxContain: controller.getMailboxContain(presentationEmail),
|
||||
presentationEmail: presentationEmail,
|
||||
position: position,
|
||||
emailLoaded: controller.currentEmailLoaded.value,
|
||||
responsiveUtils: controller.responsiveUtils,
|
||||
imagePaths: controller.imagePaths,
|
||||
username: controller.session?.username,
|
||||
handleEmailAction: (email, action) => controller.handleEmailAction(context, email, action),
|
||||
additionalActions: [
|
||||
EmailActionType.forward,
|
||||
EmailActionType.replyAll,
|
||||
EmailActionType.replyToList,
|
||||
EmailActionType.printAll,
|
||||
if (controller.responsiveUtils.isMobile(context))
|
||||
EmailActionType.moveToMailbox,
|
||||
if (!controller.responsiveUtils.isDesktop(context)) ...[
|
||||
EmailActionType.markAsStarred,
|
||||
EmailActionType.unMarkAsStarred,
|
||||
EmailActionType.moveToTrash,
|
||||
EmailActionType.deletePermanently,
|
||||
],
|
||||
],
|
||||
),
|
||||
onToggleThreadDetailCollapseExpand: onToggleThreadDetailCollapseExpand,
|
||||
onTapAvatarActionClick: onToggleThreadDetailCollapseExpand,
|
||||
mailboxContain: presentationEmail.findMailboxContain(
|
||||
controller.mailboxDashBoardController.mapMailboxById,
|
||||
),
|
||||
)),
|
||||
Obx(() => MailUnsubscribedBanner(
|
||||
presentationEmail: controller.currentEmail,
|
||||
@@ -340,7 +355,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
.ownEmailAddress
|
||||
.value,
|
||||
onMailtoAttendeesAction: controller.handleMailToAttendees,
|
||||
openEmailAddressDetailAction: controller.openEmailAddressDialog,
|
||||
openEmailAddressDetailAction: (_, emailAddress) => controller.openEmailAddressDialog(emailAddress),
|
||||
isFree: controller.isCalendarEventFree,
|
||||
listEmailAddressSender: emailAddressSender ?? [],
|
||||
isPortraitMobile: controller
|
||||
@@ -496,113 +511,4 @@ class EmailView extends GetWidget<SingleEmailController> {
|
||||
|
||||
return usernameEvent.isNotEmpty && titleEvent.isNotEmpty;
|
||||
}
|
||||
|
||||
bool canDeletePermanently(PresentationEmail email) {
|
||||
return email.mailboxContain?.isTrash
|
||||
?? email.mailboxContain?.isSpam
|
||||
?? false;
|
||||
}
|
||||
|
||||
void _handleMoreEmailAction({
|
||||
required BuildContext context,
|
||||
required PresentationEmail presentationEmail,
|
||||
RelativeRect? position,
|
||||
EmailLoaded? emailLoaded,
|
||||
}) {
|
||||
final mailboxContain = controller.getMailboxContain(presentationEmail);
|
||||
final isChildOfTeamMailboxes = mailboxContain?.isChildOfTeamMailboxes ?? false;
|
||||
final isSpam = mailboxContain?.isSpam ?? false;
|
||||
final isArchive = mailboxContain?.isArchive ?? false;
|
||||
final isTemplates = mailboxContain?.isTemplates ?? false;
|
||||
final isUnsubscribeEnabled = !presentationEmail.isSubscribed &&
|
||||
controller.emailUnsubscribe.value != null;
|
||||
final isCreateRuleEnabled = presentationEmail.from?.isNotEmpty == true;
|
||||
final isDownloadMessageAsEMLEnabled =
|
||||
PlatformInfo.isWeb && PlatformInfo.isCanvasKit;
|
||||
|
||||
final emailActions = [
|
||||
if (isInsideThreadDetailView) ...[
|
||||
EmailActionType.forward,
|
||||
if (presentationEmail.getCountMailAddressWithoutMe(controller.session?.username.value ?? '') > 1)
|
||||
EmailActionType.replyAll,
|
||||
if (EmailUtils.isReplyToListEnabled(emailLoaded?.emailCurrent?.listPost ?? ''))
|
||||
EmailActionType.replyToList,
|
||||
if (PlatformInfo.isWeb && PlatformInfo.isCanvasKit)
|
||||
EmailActionType.printAll,
|
||||
if (controller.responsiveUtils.isMobile(context))
|
||||
EmailActionType.moveToMailbox,
|
||||
if (!controller.responsiveUtils.isDesktop(context)) ...[
|
||||
presentationEmail.hasStarred
|
||||
? EmailActionType.unMarkAsStarred
|
||||
: EmailActionType.markAsStarred,
|
||||
canDeletePermanently(presentationEmail)
|
||||
? EmailActionType.deletePermanently
|
||||
: EmailActionType.moveToTrash,
|
||||
],
|
||||
],
|
||||
EmailActionType.markAsUnread,
|
||||
if (!isChildOfTeamMailboxes)
|
||||
isSpam ? EmailActionType.unSpam : EmailActionType.moveToSpam,
|
||||
if (isCreateRuleEnabled)
|
||||
EmailActionType.createRule,
|
||||
if (isUnsubscribeEnabled)
|
||||
EmailActionType.unsubscribe,
|
||||
if (!isArchive)
|
||||
EmailActionType.archiveMessage,
|
||||
if (isDownloadMessageAsEMLEnabled)
|
||||
EmailActionType.downloadMessageAsEML,
|
||||
if (!isTemplates)
|
||||
EmailActionType.editAsNewEmail,
|
||||
];
|
||||
|
||||
if (position == null) {
|
||||
final contextMenuActions = emailActions
|
||||
.map((action) => ContextItemEmailAction(
|
||||
action,
|
||||
AppLocalizations.of(context),
|
||||
controller.imagePaths,
|
||||
))
|
||||
.toList();
|
||||
|
||||
controller.mailboxDashBoardController.openBottomSheetContextMenu(
|
||||
context: context,
|
||||
itemActions: contextMenuActions,
|
||||
onContextMenuActionClick: (menuAction) {
|
||||
popBack();
|
||||
controller.handleEmailAction(
|
||||
context,
|
||||
presentationEmail,
|
||||
menuAction.action,
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
final popupMenuItems = emailActions.map((actionType) {
|
||||
return PopupMenuItem(
|
||||
padding: EdgeInsets.zero,
|
||||
child: PopupMenuItemActionWidget(
|
||||
menuAction: PopupMenuItemEmailAction(
|
||||
actionType,
|
||||
AppLocalizations.of(context),
|
||||
controller.imagePaths,
|
||||
),
|
||||
menuActionClick: (menuAction) {
|
||||
popBack();
|
||||
controller.handleEmailAction(
|
||||
context,
|
||||
presentationEmail,
|
||||
menuAction.action,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}).toList();
|
||||
|
||||
controller.mailboxDashBoardController.openPopupMenu(
|
||||
context,
|
||||
position,
|
||||
popupMenuItems,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,8 +144,8 @@ class ComposerArguments extends RouterArguments {
|
||||
|
||||
factory ComposerArguments.replyEmail({
|
||||
required PresentationEmail presentationEmail,
|
||||
required String content,
|
||||
required List<Attachment> inlineImages,
|
||||
required String? content,
|
||||
required List<Attachment>? inlineImages,
|
||||
Role? mailboxRole,
|
||||
MessageIdsHeaderValue? messageId,
|
||||
MessageIdsHeaderValue? references,
|
||||
@@ -163,8 +163,8 @@ class ComposerArguments extends RouterArguments {
|
||||
|
||||
factory ComposerArguments.replyToListEmail({
|
||||
required PresentationEmail presentationEmail,
|
||||
required String content,
|
||||
required List<Attachment> inlineImages,
|
||||
required String? content,
|
||||
required List<Attachment>? inlineImages,
|
||||
Role? mailboxRole,
|
||||
MessageIdsHeaderValue? messageId,
|
||||
MessageIdsHeaderValue? references,
|
||||
@@ -182,8 +182,8 @@ class ComposerArguments extends RouterArguments {
|
||||
|
||||
factory ComposerArguments.replyAllEmail({
|
||||
required PresentationEmail presentationEmail,
|
||||
required String content,
|
||||
required List<Attachment> inlineImages,
|
||||
required String? content,
|
||||
required List<Attachment>? inlineImages,
|
||||
Role? mailboxRole,
|
||||
MessageIdsHeaderValue? messageId,
|
||||
MessageIdsHeaderValue? references,
|
||||
@@ -201,9 +201,9 @@ class ComposerArguments extends RouterArguments {
|
||||
|
||||
factory ComposerArguments.forwardEmail({
|
||||
required PresentationEmail presentationEmail,
|
||||
required String content,
|
||||
required List<Attachment> attachments,
|
||||
required List<Attachment> inlineImages,
|
||||
required String? content,
|
||||
required List<Attachment>? attachments,
|
||||
required List<Attachment>? inlineImages,
|
||||
MessageIdsHeaderValue? messageId,
|
||||
MessageIdsHeaderValue? references,
|
||||
}) => ComposerArguments(
|
||||
|
||||
@@ -0,0 +1,886 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:core/data/network/config/dynamic_url_interceptors.dart';
|
||||
import 'package:core/domain/extensions/datetime_extension.dart';
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/presentation/utils/app_toast.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/transform_configuration.dart';
|
||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:core/presentation/views/bottom_popup/confirmation_dialog_action_sheet_builder.dart';
|
||||
import 'package:core/presentation/views/dialog/confirmation_dialog_builder.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/download/download_task_id.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_address_extension.dart';
|
||||
import 'package:model/extensions/list_email_address_extension.dart';
|
||||
import 'package:model/extensions/presentation_email_extension.dart';
|
||||
import 'package:model/extensions/presentation_mailbox_extension.dart';
|
||||
import 'package:model/extensions/session_extension.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/mixin/popup_context_menu_action_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.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/exceptions/email_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/email_print.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/model/mark_read_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/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_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/model/email_loaded.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/email_unsubscribe.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_action_cupertino_action_sheet_action_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_address_dialog_builder.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_email_rule_filter_request.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/domain/usecases/create_new_email_rule_filter_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rules_filter_creator_arguments.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/routes/app_routes.dart';
|
||||
import 'package:tmail_ui_user/main/routes/dialog_router.dart';
|
||||
import 'package:tmail_ui_user/main/routes/navigation_router.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||
import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class EmailActionReactor with MessageDialogActionMixin, PopupContextMenuActionMixin {
|
||||
const EmailActionReactor(
|
||||
this._markAsEmailReadInteractor,
|
||||
this._markAsStarEmailInteractor,
|
||||
this._createNewEmailRuleFilterInteractor,
|
||||
this._printEmailInteractor,
|
||||
this._getEmailContentInteractor,
|
||||
this._downloadAttachmentForWebInteractor,
|
||||
);
|
||||
|
||||
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
|
||||
final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
|
||||
final CreateNewEmailRuleFilterInteractor? _createNewEmailRuleFilterInteractor;
|
||||
final PrintEmailInteractor _printEmailInteractor;
|
||||
final GetEmailContentInteractor _getEmailContentInteractor;
|
||||
final DownloadAttachmentForWebInteractor _downloadAttachmentForWebInteractor;
|
||||
|
||||
Stream<Either<Failure, Success>> markAsEmailRead(
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
PresentationEmail presentationEmail, {
|
||||
required ReadActions readAction,
|
||||
}) {
|
||||
return _markAsEmailReadInteractor.execute(
|
||||
session,
|
||||
accountId,
|
||||
presentationEmail.id!,
|
||||
readAction,
|
||||
MarkReadAction.tap,
|
||||
presentationEmail.mailboxContain?.mailboxId,
|
||||
);
|
||||
}
|
||||
|
||||
Stream<Either<Failure, Success>> markAsStarEmail(
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
PresentationEmail presentationEmail, {
|
||||
required MarkStarAction markStarAction,
|
||||
}) {
|
||||
return _markAsStarEmailInteractor.execute(
|
||||
session,
|
||||
accountId,
|
||||
presentationEmail.id!,
|
||||
markStarAction,
|
||||
);
|
||||
}
|
||||
|
||||
Future<({
|
||||
MoveToMailboxRequest moveRequest,
|
||||
Map<EmailId, bool> emailIdsWithReadStatus
|
||||
})?> moveToMailbox(
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
PresentationEmail presentationEmail, {
|
||||
required Map<MailboxId, PresentationMailbox> mapMailbox,
|
||||
required PresentationMailbox? selectedMailbox,
|
||||
required bool isSearchEmailRunning,
|
||||
}) async {
|
||||
final moveRequest = await _moveToMailbox(
|
||||
session,
|
||||
accountId,
|
||||
presentationEmail,
|
||||
mapMailbox: mapMailbox,
|
||||
isSearchEmailRunning: isSearchEmailRunning,
|
||||
selectedMailbox: selectedMailbox,
|
||||
);
|
||||
if (moveRequest == null) return null;
|
||||
|
||||
return (
|
||||
moveRequest: moveRequest.moveRequest,
|
||||
emailIdsWithReadStatus: moveRequest.emailIdsWithReadStatus,
|
||||
);
|
||||
}
|
||||
|
||||
({
|
||||
MoveToMailboxRequest moveRequest,
|
||||
Map<EmailId, bool> emailIdsWithReadStatus
|
||||
})? moveToTrash(
|
||||
PresentationEmail presentationEmail, {
|
||||
required Map<MailboxId, PresentationMailbox> mapMailbox,
|
||||
required PresentationMailbox? selectedMailbox,
|
||||
required bool isSearchEmailRunning,
|
||||
required Map<Role, MailboxId> mapDefaultMailboxIdByRole,
|
||||
}) {
|
||||
final trashMailboxId = mapDefaultMailboxIdByRole[
|
||||
PresentationMailbox.roleTrash
|
||||
];
|
||||
final currentMailbox = _getMailboxContain(
|
||||
presentationEmail,
|
||||
mapMailbox: mapMailbox,
|
||||
isSearchEmailRunning: isSearchEmailRunning,
|
||||
selectedMailbox: selectedMailbox,
|
||||
);
|
||||
if (trashMailboxId == null || currentMailbox == null) return null;
|
||||
|
||||
return (
|
||||
moveRequest: MoveToMailboxRequest(
|
||||
{currentMailbox.id: [presentationEmail.id!]},
|
||||
trashMailboxId,
|
||||
MoveAction.moving,
|
||||
EmailActionType.moveToTrash),
|
||||
emailIdsWithReadStatus: {presentationEmail.id!: presentationEmail.hasRead},
|
||||
);
|
||||
}
|
||||
|
||||
void deleteEmailPermanently(
|
||||
PresentationEmail presentationEmail, {
|
||||
required void Function(PresentationEmail email) onDeleteEmailRequest,
|
||||
required ResponsiveUtils responsiveUtils,
|
||||
required ImagePaths imagePaths,
|
||||
}) async {
|
||||
if (currentContext == null || !currentContext!.mounted) return;
|
||||
if (responsiveUtils.isMobile(currentContext!)) {
|
||||
await (ConfirmationDialogActionSheetBuilder(currentContext!)
|
||||
..messageText(DeleteActionType.single.getContentDialog(currentContext!))
|
||||
..onCancelAction(AppLocalizations.of(currentContext!).cancel, () => popBack())
|
||||
..onConfirmAction(
|
||||
DeleteActionType.single.getConfirmActionName(currentContext!),
|
||||
() => onDeleteEmailRequest.call(presentationEmail)
|
||||
)
|
||||
).show();
|
||||
} else {
|
||||
await Get.dialog(
|
||||
PointerInterceptor(child: ConfirmationDialogBuilder(
|
||||
key: const Key('confirm_dialog_delete_email_permanently'),
|
||||
imagePath: imagePaths,
|
||||
title: DeleteActionType.single.getTitleDialog(currentContext!),
|
||||
textContent: DeleteActionType.single.getContentDialog(currentContext!),
|
||||
cancelText: DeleteActionType.single.getConfirmActionName(currentContext!),
|
||||
confirmText: AppLocalizations.of(currentContext!).cancel,
|
||||
onCancelButtonAction: () => onDeleteEmailRequest.call(presentationEmail),
|
||||
onConfirmButtonAction: popBack,
|
||||
onCloseButtonAction: popBack,
|
||||
)),
|
||||
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
({
|
||||
MoveToMailboxRequest moveRequest,
|
||||
Map<EmailId, bool> emailIdsWithReadStatus
|
||||
})? moveToSpam(
|
||||
PresentationEmail presentationEmail, {
|
||||
required Map<MailboxId, PresentationMailbox> mapMailbox,
|
||||
required PresentationMailbox? selectedMailbox,
|
||||
required bool isSearchEmailRunning,
|
||||
required Map<Role, MailboxId> mapDefaultMailboxIdByRole,
|
||||
}) {
|
||||
final spamMailboxId = _spamMailboxId(mapDefaultMailboxIdByRole);
|
||||
final currentMailbox = _getMailboxContain(
|
||||
presentationEmail,
|
||||
mapMailbox: mapMailbox,
|
||||
isSearchEmailRunning: isSearchEmailRunning,
|
||||
selectedMailbox: selectedMailbox,
|
||||
);
|
||||
if (spamMailboxId == null || currentMailbox == null) return null;
|
||||
|
||||
return (
|
||||
moveRequest: MoveToMailboxRequest(
|
||||
{currentMailbox.id: [presentationEmail.id!]},
|
||||
spamMailboxId,
|
||||
MoveAction.moving,
|
||||
EmailActionType.moveToSpam),
|
||||
emailIdsWithReadStatus: {presentationEmail.id!: presentationEmail.hasRead},
|
||||
);
|
||||
}
|
||||
|
||||
({
|
||||
MoveToMailboxRequest moveRequest,
|
||||
Map<EmailId, bool> emailIdsWithReadStatus
|
||||
})? unSpam(
|
||||
PresentationEmail presentationEmail, {
|
||||
required Map<MailboxId, PresentationMailbox> mapMailbox,
|
||||
required PresentationMailbox? selectedMailbox,
|
||||
required bool isSearchEmailRunning,
|
||||
required Map<Role, MailboxId> mapDefaultMailboxIdByRole,
|
||||
}) {
|
||||
final spamMailboxId = _spamMailboxId(mapDefaultMailboxIdByRole);
|
||||
final inboxMailboxId = mapDefaultMailboxIdByRole[
|
||||
PresentationMailbox.roleInbox
|
||||
];
|
||||
if (spamMailboxId == null || inboxMailboxId == null) return null;
|
||||
|
||||
return (
|
||||
moveRequest: MoveToMailboxRequest(
|
||||
{spamMailboxId: [presentationEmail.id!]},
|
||||
inboxMailboxId,
|
||||
MoveAction.moving,
|
||||
EmailActionType.unSpam
|
||||
),
|
||||
emailIdsWithReadStatus: {presentationEmail.id!: presentationEmail.hasRead},
|
||||
);
|
||||
}
|
||||
|
||||
MailboxId? _spamMailboxId(
|
||||
Map<Role, MailboxId> mapDefaultMailboxIdByRole
|
||||
) {
|
||||
return mapDefaultMailboxIdByRole[
|
||||
PresentationMailbox.roleSpam
|
||||
] ?? mapDefaultMailboxIdByRole[
|
||||
PresentationMailbox.roleJunk
|
||||
];
|
||||
}
|
||||
|
||||
Stream<Either<Failure, Success>> quickCreateRule(
|
||||
Session session,
|
||||
AccountId accountId, {
|
||||
required EmailAddress? emailAddress,
|
||||
}) async* {
|
||||
Get.back();
|
||||
final arguments = RulesFilterCreatorArguments(
|
||||
accountId,
|
||||
session,
|
||||
emailAddress: emailAddress,
|
||||
);
|
||||
|
||||
final newRuleFilterRequest = PlatformInfo.isWeb
|
||||
? await DialogRouter.pushGeneralDialog(
|
||||
routeName: AppRoutes.rulesFilterCreator,
|
||||
arguments: arguments,
|
||||
)
|
||||
: await push(AppRoutes.rulesFilterCreator, arguments: arguments);
|
||||
|
||||
if (newRuleFilterRequest is! CreateNewEmailRuleFilterRequest) return;
|
||||
|
||||
yield* _createNewEmailRuleFilterInteractor?.execute(
|
||||
accountId,
|
||||
newRuleFilterRequest
|
||||
) ?? const Stream.empty();
|
||||
}
|
||||
|
||||
Future<void> unsubscribeEmail(
|
||||
PresentationEmail presentationEmail, {
|
||||
required EmailUnsubscribe? emailUnsubscribe,
|
||||
required void Function(EmailId emailId) onUnsubscribeByHttpsLink,
|
||||
required void Function(
|
||||
EmailId emailId,
|
||||
NavigationRouter navigationRouter,
|
||||
) onUnsubscribeByMailtoLink,
|
||||
}) async {
|
||||
if (currentContext == null || !currentContext!.mounted) return;
|
||||
|
||||
await showConfirmDialogAction(
|
||||
currentContext!,
|
||||
'',
|
||||
AppLocalizations.of(currentContext!).unsubscribe,
|
||||
onConfirmAction: () {
|
||||
if (emailUnsubscribe?.httpLinks.isNotEmpty == true) {
|
||||
onUnsubscribeByHttpsLink(presentationEmail.id!);
|
||||
AppUtils.launchLink(emailUnsubscribe!.httpLinks.first);
|
||||
} else if (emailUnsubscribe?.mailtoLinks.isNotEmpty == true) {
|
||||
final navigationRouter = RouteUtils.generateNavigationRouterFromMailtoLink(
|
||||
emailUnsubscribe!.mailtoLinks.first,
|
||||
);
|
||||
onUnsubscribeByMailtoLink(presentationEmail.id!, navigationRouter);
|
||||
}
|
||||
},
|
||||
showAsBottomSheet: true,
|
||||
title: AppLocalizations.of(currentContext!).unsubscribeMail,
|
||||
listTextSpan: [
|
||||
TextSpan(text: AppLocalizations.of(currentContext!).unsubscribeMailDialogMessage),
|
||||
TextSpan(
|
||||
text: ' ${presentationEmail.getSenderName()}',
|
||||
style: ThemeUtils.textStyleBodyBody2(
|
||||
color: AppColor.steelGray400,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
const TextSpan(text: ' ?'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
void archiveMessage(
|
||||
PresentationEmail presentationEmail, {
|
||||
required void Function(
|
||||
PresentationEmail presentationEmail,
|
||||
) onArchiveEmailRequest,
|
||||
}) => onArchiveEmailRequest(presentationEmail);
|
||||
|
||||
Stream<Either<Failure, Success>> printEmail(
|
||||
PresentationEmail presentationEmail, {
|
||||
required String ownEmailAddress,
|
||||
required EmailLoaded? emailLoaded,
|
||||
VoidCallback? onGetEmailContentFailure,
|
||||
Session? session,
|
||||
AccountId? accountId,
|
||||
String? baseDownloadUrl,
|
||||
TransformConfiguration? transformConfiguration,
|
||||
}) async* {
|
||||
emailLoaded ??= await _getEmailLoaded(
|
||||
session,
|
||||
accountId,
|
||||
presentationEmail.id,
|
||||
baseDownloadUrl,
|
||||
transformConfiguration,
|
||||
);
|
||||
|
||||
if (emailLoaded == null) {
|
||||
onGetEmailContentFailure?.call();
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentContext == null || !currentContext!.mounted) return;
|
||||
final locale = Localizations.localeOf(currentContext!);
|
||||
final appLocalizations = AppLocalizations.of(currentContext!);
|
||||
|
||||
yield* _printEmailInteractor.execute(
|
||||
EmailPrint(
|
||||
appName: appLocalizations.app_name,
|
||||
userName: ownEmailAddress,
|
||||
attachments: emailLoaded.attachments,
|
||||
emailContent: emailLoaded.htmlContent,
|
||||
fromPrefix: appLocalizations.from_email_address_prefix,
|
||||
toPrefix: appLocalizations.to_email_address_prefix,
|
||||
ccPrefix: appLocalizations.cc_email_address_prefix,
|
||||
bccPrefix: appLocalizations.bcc_email_address_prefix,
|
||||
replyToPrefix: appLocalizations.replyToEmailAddressPrefix,
|
||||
titleAttachment: appLocalizations.attachments.toLowerCase(),
|
||||
toAddress: presentationEmail.to?.listEmailAddressToString(isFullEmailAddress: true),
|
||||
ccAddress: presentationEmail.cc?.listEmailAddressToString(isFullEmailAddress: true),
|
||||
bccAddress: presentationEmail.bcc?.listEmailAddressToString(isFullEmailAddress: true),
|
||||
replyToAddress: presentationEmail.replyTo?.listEmailAddressToString(isFullEmailAddress: true),
|
||||
sender: presentationEmail.from?.isNotEmpty == true
|
||||
? presentationEmail.from!.first
|
||||
: null,
|
||||
receiveTime: presentationEmail.getReceivedAt(
|
||||
locale.toLanguageTag(),
|
||||
pattern: presentationEmail.receivedAt
|
||||
?.value
|
||||
.toLocal()
|
||||
.toPatternForPrinting(locale.toLanguageTag()),
|
||||
),
|
||||
subject: presentationEmail.subject,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Stream<Either<Failure, Success>> downloadMessageAsEML(
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
PresentationEmail presentationEmail, {
|
||||
required StreamController<Either<Failure, Success>> downloadProgressStateController,
|
||||
}) async* {
|
||||
final emlAttachment = presentationEmail.createEMLAttachment();
|
||||
if (emlAttachment.blobId == null) {
|
||||
yield* Stream.value(Left(DownloadAttachmentForWebFailure(
|
||||
exception: NotFoundEmailBlobIdException(),
|
||||
)));
|
||||
return;
|
||||
}
|
||||
|
||||
final generateTaskId = DownloadTaskId(const Uuid().v4());
|
||||
try {
|
||||
final baseDownloadUrl = session.getDownloadUrl(
|
||||
jmapUrl: getBinding<DynamicUrlInterceptors>()?.jmapUrl,
|
||||
);
|
||||
final cancelToken = CancelToken();
|
||||
yield* _downloadAttachmentForWebInteractor.execute(
|
||||
generateTaskId,
|
||||
emlAttachment,
|
||||
accountId,
|
||||
baseDownloadUrl,
|
||||
downloadProgressStateController,
|
||||
cancelToken: cancelToken,
|
||||
previewerSupported: false,
|
||||
);
|
||||
} catch (e) {
|
||||
logError('SingleEmailController::downloadAttachmentForWeb(): $e');
|
||||
yield* Stream.value(Left(DownloadAttachmentForWebFailure(
|
||||
attachment: emlAttachment,
|
||||
taskId: generateTaskId,
|
||||
exception: e,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
void editAsNewEmail(
|
||||
PresentationEmail presentationEmail, {
|
||||
required void Function(
|
||||
PresentationEmail presentationEmail,
|
||||
) onEditAsEmailRequest,
|
||||
}) => onEditAsEmailRequest(presentationEmail);
|
||||
|
||||
void replyEmail(
|
||||
PresentationEmail presentationEmail, {
|
||||
required void Function(
|
||||
PresentationEmail presentationEmail,
|
||||
EmailLoaded? emailLoaded,
|
||||
) onReplyEmailRequest,
|
||||
required EmailLoaded? emailLoaded,
|
||||
}) {
|
||||
onReplyEmailRequest(presentationEmail, emailLoaded);
|
||||
}
|
||||
|
||||
void replyAll(
|
||||
PresentationEmail presentationEmail, {
|
||||
required void Function(
|
||||
PresentationEmail presentationEmail,
|
||||
EmailLoaded? emailLoaded,
|
||||
) onReplyAllRequest,
|
||||
required EmailLoaded? emailLoaded,
|
||||
}) {
|
||||
onReplyAllRequest(presentationEmail, emailLoaded);
|
||||
}
|
||||
|
||||
void replyToList(
|
||||
PresentationEmail presentationEmail, {
|
||||
required void Function(
|
||||
PresentationEmail presentationEmail,
|
||||
EmailLoaded? emailLoaded,
|
||||
) onReplyToListRequest,
|
||||
required EmailLoaded? emailLoaded,
|
||||
}) {
|
||||
onReplyToListRequest(presentationEmail, emailLoaded);
|
||||
}
|
||||
|
||||
void forward(
|
||||
PresentationEmail presentationEmail, {
|
||||
required void Function(
|
||||
PresentationEmail presentationEmail,
|
||||
EmailLoaded? emailLoaded,
|
||||
) onForwardRequest,
|
||||
required EmailLoaded? emailLoaded,
|
||||
}) {
|
||||
onForwardRequest(presentationEmail, emailLoaded);
|
||||
}
|
||||
|
||||
void handleMoreEmailAction({
|
||||
required PresentationEmail presentationEmail,
|
||||
required PresentationMailbox? mailboxContain,
|
||||
required RelativeRect? position,
|
||||
required ResponsiveUtils responsiveUtils,
|
||||
required ImagePaths imagePaths,
|
||||
required UserName? username,
|
||||
required void Function(
|
||||
PresentationEmail presentationEmail,
|
||||
EmailActionType action,
|
||||
) handleEmailAction,
|
||||
required List<EmailActionType> additionalActions,
|
||||
}) {
|
||||
if (currentContext == null) return;
|
||||
|
||||
final moreActions = [
|
||||
if (additionalActions.contains(EmailActionType.forward))
|
||||
EmailActionType.forward,
|
||||
if (presentationEmail.getCountMailAddressWithoutMe(username?.value ?? '') > 1 &&
|
||||
additionalActions.contains(EmailActionType.replyAll))
|
||||
EmailActionType.replyAll,
|
||||
if (EmailUtils.isReplyToListEnabled(presentationEmail.listPost ?? '') &&
|
||||
additionalActions.contains(EmailActionType.replyToList))
|
||||
EmailActionType.replyToList,
|
||||
if (PlatformInfo.isWeb &&
|
||||
PlatformInfo.isCanvasKit &&
|
||||
additionalActions.contains(EmailActionType.printAll))
|
||||
EmailActionType.printAll,
|
||||
if (additionalActions.contains(EmailActionType.moveToMailbox))
|
||||
EmailActionType.moveToMailbox,
|
||||
if (additionalActions.contains(EmailActionType.markAsStarred) &&
|
||||
additionalActions.contains(EmailActionType.unMarkAsStarred))
|
||||
presentationEmail.hasStarred
|
||||
? EmailActionType.unMarkAsStarred
|
||||
: EmailActionType.markAsStarred,
|
||||
if (additionalActions.contains(EmailActionType.moveToTrash) &&
|
||||
additionalActions.contains(EmailActionType.deletePermanently))
|
||||
_canDeletePermanently(presentationEmail)
|
||||
? EmailActionType.deletePermanently
|
||||
: EmailActionType.moveToTrash,
|
||||
EmailActionType.markAsUnread,
|
||||
if (mailboxContain?.isChildOfTeamMailboxes == false)
|
||||
if (mailboxContain?.isSpam == true)
|
||||
EmailActionType.unSpam
|
||||
else
|
||||
EmailActionType.moveToSpam,
|
||||
if (presentationEmail.from?.isNotEmpty == true)
|
||||
EmailActionType.createRule,
|
||||
if (!presentationEmail.isSubscribed && presentationEmail.listUnsubscribe != null)
|
||||
EmailActionType.unsubscribe,
|
||||
if (mailboxContain?.isArchive == false)
|
||||
EmailActionType.archiveMessage,
|
||||
if (PlatformInfo.isWeb && PlatformInfo.isCanvasKit)
|
||||
EmailActionType.downloadMessageAsEML,
|
||||
EmailActionType.editAsNewEmail,
|
||||
];
|
||||
|
||||
if (position == null) {
|
||||
openContextMenuAction(
|
||||
currentContext!,
|
||||
_emailActionMoreActionTile(
|
||||
currentContext!,
|
||||
presentationEmail,
|
||||
moreActions,
|
||||
responsiveUtils,
|
||||
imagePaths,
|
||||
handleEmailAction: handleEmailAction,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
openPopupMenuAction(
|
||||
currentContext!,
|
||||
position,
|
||||
_popupMenuEmailActionTile(
|
||||
currentContext!,
|
||||
presentationEmail,
|
||||
moreActions,
|
||||
imagePaths,
|
||||
handleEmailAction: handleEmailAction,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool _canDeletePermanently(PresentationEmail email) {
|
||||
return email.mailboxContain?.isTrash
|
||||
?? email.mailboxContain?.isSpam
|
||||
?? false;
|
||||
}
|
||||
|
||||
List<Widget> _emailActionMoreActionTile(
|
||||
BuildContext context,
|
||||
PresentationEmail presentationEmail,
|
||||
List<EmailActionType> actionTypes,
|
||||
ResponsiveUtils responsiveUtils,
|
||||
ImagePaths imagePaths, {
|
||||
required void Function(
|
||||
PresentationEmail presentationEmail,
|
||||
EmailActionType action,
|
||||
) handleEmailAction
|
||||
}) {
|
||||
return actionTypes.map((action) {
|
||||
return (EmailActionCupertinoActionSheetActionBuilder(
|
||||
Key('${action.name}_action'),
|
||||
SvgPicture.asset(
|
||||
action.getIcon(imagePaths),
|
||||
width: 24,
|
||||
height: 24,
|
||||
fit: BoxFit.fill,
|
||||
colorFilter: AppColor.colorTextButton.asFilter()
|
||||
),
|
||||
action.getTitle(AppLocalizations.of(context)),
|
||||
presentationEmail,
|
||||
iconLeftPadding: responsiveUtils.isScreenWithShortestSide(context)
|
||||
? const EdgeInsetsDirectional.only(start: 12, end: 16)
|
||||
: const EdgeInsetsDirectional.only(end: 12),
|
||||
iconRightPadding: responsiveUtils.isScreenWithShortestSide(context)
|
||||
? const EdgeInsetsDirectional.only(end: 12)
|
||||
: EdgeInsets.zero
|
||||
)
|
||||
..onActionClick((presentationEmail) {
|
||||
popBack();
|
||||
handleEmailAction(presentationEmail, action);
|
||||
})).build();
|
||||
}).toList();
|
||||
}
|
||||
|
||||
List<PopupMenuEntry> _popupMenuEmailActionTile(
|
||||
BuildContext context,
|
||||
PresentationEmail presentationEmail,
|
||||
List<EmailActionType> actionTypes,
|
||||
ImagePaths imagePaths, {
|
||||
required void Function(
|
||||
PresentationEmail presentationEmail,
|
||||
EmailActionType action,
|
||||
) handleEmailAction,
|
||||
}) {
|
||||
return actionTypes.map((action) {
|
||||
return PopupMenuItem(
|
||||
key: Key('${action.name}_action'),
|
||||
padding: EdgeInsets.zero,
|
||||
child: PopupItemWidget(
|
||||
iconAction: action.getIcon(imagePaths),
|
||||
nameAction: action.getTitle(AppLocalizations.of(context)),
|
||||
colorIcon: AppColor.colorTextButton,
|
||||
padding: const EdgeInsetsDirectional.only(start: 12),
|
||||
styleName: const TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 16,
|
||||
color: Colors.black
|
||||
),
|
||||
onCallbackAction: () {
|
||||
popBack();
|
||||
handleEmailAction(presentationEmail, action);
|
||||
}
|
||||
)
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
void openEmailAddressDialog(
|
||||
Session session,
|
||||
AccountId accountId, {
|
||||
required EmailAddress emailAddress,
|
||||
required ResponsiveUtils responsiveUtils,
|
||||
required ImagePaths imagePaths,
|
||||
required AppToast appToast,
|
||||
required void Function(EmailAddress emailAddress) onComposeEmailFromEmailAddressRequest,
|
||||
required void Function(Stream<Either<Failure, Success>> quickCreateRuleStream) onQuickCreateRuleRequest,
|
||||
}) {
|
||||
if (currentContext?.mounted != true) return;
|
||||
|
||||
if (responsiveUtils.isScreenWithShortestSide(currentContext!)) {
|
||||
Get.bottomSheet(
|
||||
PointerInterceptor(
|
||||
child: EmailAddressBottomSheetBuilder(
|
||||
imagePaths: imagePaths,
|
||||
emailAddress: emailAddress,
|
||||
onCloseDialogAction: popBack,
|
||||
onCopyEmailAddressAction: (emailAddress) =>
|
||||
_copyEmailAddress(currentContext!, emailAddress, appToast),
|
||||
onComposeEmailAction: (emailAddress) =>
|
||||
onComposeEmailFromEmailAddressRequest(emailAddress),
|
||||
onQuickCreatingRuleEmailDialogAction: (emailAddress) =>
|
||||
onQuickCreateRuleRequest(
|
||||
quickCreateRule(session, accountId, emailAddress: emailAddress),
|
||||
),
|
||||
),
|
||||
),
|
||||
useRootNavigator: true,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadiusDirectional.only(
|
||||
topStart: Radius.circular(16.0),
|
||||
topEnd: Radius.circular(16.0),
|
||||
),
|
||||
),
|
||||
isScrollControlled: true,
|
||||
enableDrag: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
} else {
|
||||
Get.dialog(
|
||||
PointerInterceptor(
|
||||
child: EmailAddressDialogBuilder(
|
||||
imagePaths: imagePaths,
|
||||
emailAddress: emailAddress,
|
||||
onCloseDialogAction: popBack,
|
||||
onCopyEmailAddressAction: (emailAddress) =>
|
||||
_copyEmailAddress(currentContext!, emailAddress, appToast),
|
||||
onComposeEmailAction: (emailAddress) =>
|
||||
onComposeEmailFromEmailAddressRequest(emailAddress),
|
||||
onQuickCreatingRuleEmailDialogAction: (emailAddress) =>
|
||||
onQuickCreateRuleRequest(
|
||||
quickCreateRule(session, accountId, emailAddress: emailAddress),
|
||||
),
|
||||
),
|
||||
),
|
||||
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _copyEmailAddress(
|
||||
BuildContext context,
|
||||
EmailAddress emailAddress,
|
||||
AppToast appToast,
|
||||
) {
|
||||
Clipboard.setData(ClipboardData(text: emailAddress.emailAddress));
|
||||
appToast.showToastSuccessMessage(
|
||||
context,
|
||||
AppLocalizations.of(context).email_address_copied_to_clipboard,
|
||||
);
|
||||
}
|
||||
|
||||
Future<({
|
||||
Map<EmailId, bool> emailIdsWithReadStatus,
|
||||
MoveToMailboxRequest moveRequest,
|
||||
})?> _moveToMailbox(
|
||||
Session session,
|
||||
AccountId accountId,
|
||||
PresentationEmail presentationEmail, {
|
||||
required Map<MailboxId, PresentationMailbox> mapMailbox,
|
||||
PresentationMailbox? selectedMailbox,
|
||||
bool isSearchEmailRunning = false,
|
||||
}) async {
|
||||
final currentMailbox = _getMailboxContain(
|
||||
presentationEmail,
|
||||
mapMailbox: mapMailbox,
|
||||
selectedMailbox: selectedMailbox,
|
||||
isSearchEmailRunning: isSearchEmailRunning,
|
||||
);
|
||||
|
||||
if (currentMailbox == null) return null;
|
||||
|
||||
final arguments = DestinationPickerArguments(
|
||||
accountId,
|
||||
MailboxActions.moveEmail,
|
||||
session,
|
||||
mailboxIdSelected: currentMailbox.mailboxId
|
||||
);
|
||||
|
||||
final destinationMailbox = PlatformInfo.isWeb
|
||||
? await DialogRouter.pushGeneralDialog(routeName: AppRoutes.destinationPicker, arguments: arguments)
|
||||
: await push(AppRoutes.destinationPicker, arguments: arguments);
|
||||
|
||||
if (destinationMailbox is PresentationMailbox) {
|
||||
return _generateMoveMailboxRequest(
|
||||
accountId,
|
||||
session,
|
||||
presentationEmail,
|
||||
currentMailbox,
|
||||
destinationMailbox,
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
PresentationMailbox? _getMailboxContain(
|
||||
PresentationEmail presentationEmail, {
|
||||
required Map<MailboxId, PresentationMailbox> mapMailbox,
|
||||
PresentationMailbox? selectedMailbox,
|
||||
bool isSearchEmailRunning = false,
|
||||
}) {
|
||||
if (selectedMailbox == null || isSearchEmailRunning) {
|
||||
return presentationEmail.findMailboxContain(mapMailbox);
|
||||
}
|
||||
|
||||
return selectedMailbox;
|
||||
}
|
||||
|
||||
({
|
||||
MoveToMailboxRequest moveRequest,
|
||||
Map<EmailId, bool> emailIdsWithReadStatus,
|
||||
}) _generateMoveMailboxRequest(
|
||||
AccountId accountId,
|
||||
Session session,
|
||||
PresentationEmail emailSelected,
|
||||
PresentationMailbox currentMailbox,
|
||||
PresentationMailbox destinationMailbox
|
||||
) {
|
||||
if (destinationMailbox.isTrash) {
|
||||
return (
|
||||
moveRequest: MoveToMailboxRequest(
|
||||
{currentMailbox.id: [emailSelected.id!]},
|
||||
destinationMailbox.id,
|
||||
MoveAction.moving,
|
||||
EmailActionType.moveToTrash,
|
||||
),
|
||||
emailIdsWithReadStatus: {emailSelected.id!: emailSelected.hasRead},
|
||||
);
|
||||
} else if (destinationMailbox.isSpam) {
|
||||
return (
|
||||
moveRequest: MoveToMailboxRequest(
|
||||
{currentMailbox.id: [emailSelected.id!]},
|
||||
destinationMailbox.id,
|
||||
MoveAction.moving,
|
||||
EmailActionType.moveToSpam,
|
||||
),
|
||||
emailIdsWithReadStatus: {emailSelected.id!: emailSelected.hasRead},
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
moveRequest: MoveToMailboxRequest(
|
||||
{currentMailbox.id: [emailSelected.id!]},
|
||||
destinationMailbox.id,
|
||||
MoveAction.moving,
|
||||
EmailActionType.moveToMailbox,
|
||||
destinationPath: destinationMailbox.mailboxPath),
|
||||
emailIdsWithReadStatus: {emailSelected.id!: emailSelected.hasRead},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<EmailLoaded?> _getEmailLoaded(
|
||||
Session? session,
|
||||
AccountId? accountId,
|
||||
EmailId? emailId,
|
||||
String? baseDownloadUrl,
|
||||
TransformConfiguration? transformConfiguration,
|
||||
) {
|
||||
if (session == null ||
|
||||
accountId == null ||
|
||||
emailId == null ||
|
||||
baseDownloadUrl == null ||
|
||||
transformConfiguration == null
|
||||
) {
|
||||
return Future.value(null);
|
||||
}
|
||||
|
||||
return _getEmailContentInteractor
|
||||
.execute(
|
||||
session,
|
||||
accountId,
|
||||
emailId,
|
||||
baseDownloadUrl,
|
||||
transformConfiguration,
|
||||
)
|
||||
.last
|
||||
.then(
|
||||
(value) {
|
||||
return value.fold(
|
||||
(failure) => null,
|
||||
(success) => success is GetEmailContentSuccess
|
||||
? EmailLoaded(
|
||||
htmlContent: success.htmlEmailContent,
|
||||
attachments: List.of(success.attachments ?? []),
|
||||
inlineImages: List.of(success.inlineImages ?? []),
|
||||
emailCurrent: success.emailCurrent,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
},
|
||||
onError: (error) {
|
||||
logError('EmailActionReactor::_getEmailLoaded(): error: $error');
|
||||
return null;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@ class EmailViewAppBarWidget extends StatelessWidget {
|
||||
final BoxDecoration? appBarDecoration;
|
||||
final EmailLoaded? emailLoaded;
|
||||
final bool isInsideThreadDetailView;
|
||||
final double? height;
|
||||
final EdgeInsetsGeometry? iconPadding;
|
||||
final EdgeInsetsGeometry? iconMargin;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
@@ -49,7 +48,6 @@ class EmailViewAppBarWidget extends StatelessWidget {
|
||||
this.supportBackAction = true,
|
||||
this.appBarDecoration,
|
||||
this.isInsideThreadDetailView = false,
|
||||
this.height,
|
||||
this.iconPadding,
|
||||
this.iconMargin,
|
||||
this.padding,
|
||||
@@ -59,9 +57,9 @@ class EmailViewAppBarWidget extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final child = LayoutBuilder(builder: (context, constraints) {
|
||||
return Container(
|
||||
height: height ?? (PlatformInfo.isIOS
|
||||
height: PlatformInfo.isIOS
|
||||
? EmailViewAppBarWidgetStyles.heightIOS(context, _responsiveUtils)
|
||||
: EmailViewAppBarWidgetStyles.height),
|
||||
: EmailViewAppBarWidgetStyles.height,
|
||||
padding: padding ?? (PlatformInfo.isIOS
|
||||
? EmailViewAppBarWidgetStyles.paddingIOS(context, _responsiveUtils)
|
||||
: EmailViewAppBarWidgetStyles.padding),
|
||||
@@ -248,7 +246,8 @@ class EmailViewAppBarWidget extends StatelessWidget {
|
||||
}) {
|
||||
if (!isInsideThreadDetailView) {
|
||||
return [
|
||||
_getPrintButton(appLocalizations),
|
||||
if (PlatformInfo.isWeb && PlatformInfo.isCanvasKit)
|
||||
_getPrintButton(appLocalizations),
|
||||
_getMoveEmailButton(appLocalizations),
|
||||
_getMarkStarButton(appLocalizations),
|
||||
_getDeleteButton(appLocalizations),
|
||||
|
||||
+29
-14
@@ -5,15 +5,19 @@ import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:core/presentation/views/image/avatar_builder.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/extensions/presentation_email_extension.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/email_avatar_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/email_unsubscribe.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/smime_signature_status.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/widgets/email_receiver_widget.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_sender_builder.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_app_bar_widget.dart';
|
||||
@@ -36,6 +40,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
|
||||
final bool showRecipients;
|
||||
final VoidCallback? onToggleThreadDetailCollapseExpand;
|
||||
final OnTapAvatarActionClick? onTapAvatarActionClick;
|
||||
final PresentationMailbox? mailboxContain;
|
||||
|
||||
const InformationSenderAndReceiverBuilder({
|
||||
Key? key,
|
||||
@@ -53,6 +58,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
|
||||
this.showRecipients = true,
|
||||
this.onToggleThreadDetailCollapseExpand,
|
||||
this.onTapAvatarActionClick,
|
||||
this.mailboxContain,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -127,21 +133,30 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
|
||||
padding: const EdgeInsetsDirectional.only(start: 16, top: 2),
|
||||
),
|
||||
if (isInsideThreadDetailView)
|
||||
EmailViewAppBarWidget(
|
||||
key: const Key('email_view_app_bar_widget'),
|
||||
presentationEmail: emailSelected,
|
||||
isSearchActivated: false,
|
||||
onBackAction: () {},
|
||||
onEmailActionClick: onEmailActionClick,
|
||||
onMoreActionClick: onMoreActionClick,
|
||||
supportBackAction: false,
|
||||
appBarDecoration: const BoxDecoration(),
|
||||
emailLoaded: emailLoaded,
|
||||
isInsideThreadDetailView: isInsideThreadDetailView,
|
||||
SizedBox(
|
||||
height: IconUtils.defaultIconSize,
|
||||
iconPadding: EdgeInsets.zero,
|
||||
iconMargin: const EdgeInsetsDirectional.only(start: 16),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: OverflowBox(
|
||||
maxHeight: PlatformInfo.isIOS
|
||||
? EmailViewAppBarWidgetStyles.heightIOS(context, responsiveUtils)
|
||||
: EmailViewAppBarWidgetStyles.height,
|
||||
fit: OverflowBoxFit.deferToChild,
|
||||
child: EmailViewAppBarWidget(
|
||||
key: const Key('email_view_app_bar_widget'),
|
||||
presentationEmail: emailSelected,
|
||||
mailboxContain: mailboxContain,
|
||||
isSearchActivated: false,
|
||||
onBackAction: () {},
|
||||
onEmailActionClick: onEmailActionClick,
|
||||
onMoreActionClick: onMoreActionClick,
|
||||
supportBackAction: false,
|
||||
appBarDecoration: const BoxDecoration(),
|
||||
emailLoaded: emailLoaded,
|
||||
isInsideThreadDetailView: isInsideThreadDetailView,
|
||||
iconPadding: const EdgeInsets.all(8),
|
||||
iconMargin: EdgeInsets.zero,
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user