TF-1718 Implement unsubscribeMail on Jmap server

Signed-off-by: dab246 <tdvu@linagora.com>
(cherry picked from commit 0f61a97aab513cda75c65e3c92ebcf8f6290b6ec)
This commit is contained in:
dab246
2023-11-16 12:48:38 +07:00
committed by Dat Vu
parent 4d8c7dc52e
commit a6ecaf321d
18 changed files with 169 additions and 36 deletions
@@ -231,6 +231,7 @@ extension AppColor on Color {
static const colorDropDownItemTitleComposer = Color(0xFF0A0A0A); static const colorDropDownItemTitleComposer = Color(0xFF0A0A0A);
static const messageDialogColor = Color(0xFF8C9CAF); static const messageDialogColor = Color(0xFF8C9CAF);
static const messageDialogHighlightColor = Color(0xFF37383A); static const messageDialogHighlightColor = Color(0xFF37383A);
static const labelColor = Color(0xFF71767C);
static const mapGradientColor = [ static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)], [Color(0xFF21D4FD), Color(0xFFB721FF)],
@@ -14,6 +14,7 @@ class EmailRequest with EquatableMixin {
final IdentityId? identityId; final IdentityId? identityId;
final EmailActionType emailActionType; final EmailActionType emailActionType;
final String? storedSendingId; final String? storedSendingId;
final EmailId? previousEmailId;
EmailRequest({ EmailRequest({
required this.email, required this.email,
@@ -23,6 +24,7 @@ class EmailRequest with EquatableMixin {
this.emailIdDestroyed, this.emailIdDestroyed,
this.emailIdAnsweredOrForwarded, this.emailIdAnsweredOrForwarded,
this.storedSendingId, this.storedSendingId,
this.previousEmailId,
}); });
@override @override
@@ -34,6 +36,7 @@ class EmailRequest with EquatableMixin {
emailIdAnsweredOrForwarded, emailIdAnsweredOrForwarded,
emailActionType, emailActionType,
storedSendingId, storedSendingId,
previousEmailId,
]; ];
bool get isEmailAnswered => emailIdAnsweredOrForwarded != null && bool get isEmailAnswered => emailIdAnsweredOrForwarded != null &&
@@ -12,18 +12,18 @@ class SendEmailLoading extends UIState {}
class SendEmailSuccess extends UIActionState { class SendEmailSuccess extends UIActionState {
final String? storedSendingId; final EmailRequest emailRequest;
SendEmailSuccess({ SendEmailSuccess({
jmap.State? currentEmailState, jmap.State? currentEmailState,
jmap.State? currentMailboxState, jmap.State? currentMailboxState,
this.storedSendingId, required this.emailRequest,
}) : super(currentEmailState, currentMailboxState); }) : super(currentEmailState, currentMailboxState);
@override @override
List<Object?> get props => [ List<Object?> get props => [
...super.props, ...super.props,
storedSendingId, emailRequest,
]; ];
} }
@@ -52,7 +52,7 @@ class SendEmailInteractor {
SendEmailSuccess( SendEmailSuccess(
currentEmailState: currentEmailState, currentEmailState: currentEmailState,
currentMailboxState: currentMailboxState, currentMailboxState: currentMailboxState,
storedSendingId: emailRequest.storedSendingId emailRequest: emailRequest
) )
); );
} else { } else {
@@ -489,9 +489,7 @@ class ComposerController extends BaseController {
isInitialRecipient.value = true; isInitialRecipient.value = true;
toAddressExpandMode.value = ExpandMode.COLLAPSE; toAddressExpandMode.value = ExpandMode.COLLAPSE;
} }
if (arguments.body?.isNotEmpty == true) { _getEmailContentFromMailtoUri(arguments.body ?? '');
_getEmailContentFromMailtoUri(arguments.body!);
}
_updateStatusEmailSendButton(); _updateStatusEmailSendButton();
break; break;
case EmailActionType.reply: case EmailActionType.reply:
@@ -537,9 +535,7 @@ class ComposerController extends BaseController {
isInitialRecipient.value = true; isInitialRecipient.value = true;
toAddressExpandMode.value = ExpandMode.COLLAPSE; toAddressExpandMode.value = ExpandMode.COLLAPSE;
} }
if (arguments.body?.isNotEmpty == true) { _getEmailContentFromUnsubscribeMailtoLink(arguments.body ?? '');
_getEmailContentFromUnsubscribeMailtoLink(arguments.body!);
}
_updateStatusEmailSendButton(); _updateStatusEmailSendButton();
break; break;
default: default:
@@ -969,7 +965,8 @@ class ComposerController extends BaseController {
? arguments.presentationEmail?.id ? arguments.presentationEmail?.id
: null, : null,
emailIdAnsweredOrForwarded: arguments.presentationEmail?.id, emailIdAnsweredOrForwarded: arguments.presentationEmail?.id,
emailActionType: arguments.emailActionType emailActionType: arguments.emailActionType,
previousEmailId: arguments.previousEmailId,
); );
final mailboxRequest = mailboxDashBoardController.outboxMailbox?.id == null final mailboxRequest = mailboxDashBoardController.outboxMailbox?.id == null
@@ -32,6 +32,7 @@ import 'package:tmail_ui_user/features/email/domain/model/detailed_email.dart';
import 'package:tmail_ui_user/features/email/domain/model/event_action.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/mark_read_action.dart';
import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/unsubscribe_email_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/parse_calendar_event_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/parse_calendar_event_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/store_opened_email_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart'; import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
@@ -231,6 +232,14 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
mailboxDashBoardController.clearEmailUIAction(); mailboxDashBoardController.clearEmailUIAction();
} }
}); });
ever(mailboxDashBoardController.viewState, (viewState) {
viewState.map((success) {
if (success is UnsubscribeEmailSuccess) {
emailUnsubscribe.value = null;
}
});
});
} }
bool isListEmailContainSelectedEmail(PresentationEmail selectedEmail) { bool isListEmailContainSelectedEmail(PresentationEmail selectedEmail) {
@@ -441,7 +450,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
_handleReadReceipt(); _handleReadReceipt();
} }
if (success.emailCurrent?.hasListUnsubscribe == true) { if (currentEmail?.isSubscribed == false && success.emailCurrent?.hasListUnsubscribe == true) {
_handleUnsubscribe(success.emailCurrent!.listUnsubscribe); _handleUnsubscribe(success.emailCurrent!.listUnsubscribe);
} else { } else {
emailUnsubscribe.value = null; emailUnsubscribe.value = null;
@@ -501,7 +510,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
_handleReadReceipt(); _handleReadReceipt();
} }
if (success.emailCurrent?.hasListUnsubscribe == true) { if (currentEmail?.isSubscribed == false && success.emailCurrent?.hasListUnsubscribe == true) {
_handleUnsubscribe(success.emailCurrent!.listUnsubscribe); _handleUnsubscribe(success.emailCurrent!.listUnsubscribe);
} else { } else {
emailUnsubscribe.value = null; emailUnsubscribe.value = null;
@@ -951,11 +960,9 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
} }
} }
void _markAsEmailStarSuccess(Success success) { void _markAsEmailStarSuccess(MarkAsStarEmailSuccess success) {
if (success is MarkAsStarEmailSuccess) { final selectedEmail = mailboxDashBoardController.selectedEmail.value;
final selectedEmail = mailboxDashBoardController.selectedEmail.value; mailboxDashBoardController.setSelectedEmail(selectedEmail?.updateKeywords(success.updatedEmail.keywords));
mailboxDashBoardController.setSelectedEmail(selectedEmail?.updateKeywords(success.updatedEmail.keywords));
}
mailboxDashBoardController.dispatchState(Right(success)); mailboxDashBoardController.dispatchState(Right(success));
} }
@@ -1406,9 +1413,17 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
AppLocalizations.of(context).unsubscribe, AppLocalizations.of(context).unsubscribe,
onConfirmAction: () { onConfirmAction: () {
if (emailUnsubscribe.value?.httpLinks.isNotEmpty == true) { if (emailUnsubscribe.value?.httpLinks.isNotEmpty == true) {
_handleUnsubscribeMailByHttpsLink(context, emailUnsubscribe.value!.httpLinks); _handleUnsubscribeMailByHttpsLink(
context: context,
emailId: presentationEmail.id!,
httpLinks: emailUnsubscribe.value!.httpLinks
);
} else if (emailUnsubscribe.value?.mailtoLinks.isNotEmpty == true) { } else if (emailUnsubscribe.value?.mailtoLinks.isNotEmpty == true) {
_handleUnsubscribeMailByMailtoLink(context, emailUnsubscribe.value!.mailtoLinks); _handleUnsubscribeMailByMailtoLink(
context: context,
emailId: presentationEmail.id!,
mailtoLinks: emailUnsubscribe.value!.mailtoLinks
);
} }
}, },
showAsBottomSheet: true, showAsBottomSheet: true,
@@ -1434,24 +1449,29 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
); );
} }
void _handleUnsubscribeMailByHttpsLink(BuildContext context, List<String> httpLinks) async { void _handleUnsubscribeMailByHttpsLink({
required BuildContext context,
required EmailId emailId,
required List<String> httpLinks
}) {
log('SingleEmailController::_handleUnsubscribeMailByHttpsLink:httpLinks: $httpLinks'); log('SingleEmailController::_handleUnsubscribeMailByHttpsLink:httpLinks: $httpLinks');
final result = await AppUtils.launchLink(httpLinks.first); mailboxDashBoardController.unsubscribeMail(emailId);
if (result && context.mounted) { AppUtils.launchLink(httpLinks.first);
_appToast.showToastSuccessMessage(
context,
AppLocalizations.of(context).unsubscribedFromThisMailingList);
}
} }
void _handleUnsubscribeMailByMailtoLink(BuildContext context, List<String> mailtoLinks) { void _handleUnsubscribeMailByMailtoLink({
required BuildContext context,
required EmailId emailId,
required List<String> mailtoLinks
}) {
log('SingleEmailController::_handleUnsubscribeMailByMailtoLink:mailtoLinks: $mailtoLinks'); log('SingleEmailController::_handleUnsubscribeMailByMailtoLink:mailtoLinks: $mailtoLinks');
final navigationRouter = RouteUtils.generateNavigationRouterFromMailtoLink(mailtoLinks.first); final navigationRouter = RouteUtils.generateNavigationRouterFromMailtoLink(mailtoLinks.first);
mailboxDashBoardController.goToComposer( mailboxDashBoardController.goToComposer(
ComposerArguments.fromUnsubscribeMailtoLink( ComposerArguments.fromUnsubscribeMailtoLink(
emailAddress: navigationRouter.emailAddress, emailAddress: navigationRouter.emailAddress,
subject: navigationRouter.subject, subject: navigationRouter.subject,
body: navigationRouter.body body: navigationRouter.body,
previousEmailId: emailId,
) )
); );
} }
@@ -33,6 +33,7 @@ import 'package:tmail_ui_user/features/email/presentation/widgets/email_subject_
import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_empty_widget.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_empty_widget.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_loading_bar_widget.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/email_view_loading_bar_widget.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/information_sender_and_receiver_builder.dart'; 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/manage_account/presentation/extensions/vacation_response_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/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/localizations/app_localizations.dart';
@@ -307,6 +308,10 @@ class EmailView extends GetWidget<SingleEmailController> {
openEmailAddressDetailAction: controller.openEmailAddressDialog, openEmailAddressDetailAction: controller.openEmailAddressDialog,
onEmailActionClick: (presentationEmail, actionType) => controller.handleEmailAction(context, presentationEmail, actionType), onEmailActionClick: (presentationEmail, actionType) => controller.handleEmailAction(context, presentationEmail, actionType),
)), )),
Obx(() => MailUnsubscribedBanner(
presentationEmail: controller.currentEmail,
emailUnsubscribe: controller.emailUnsubscribe.value
)),
Obx(() { Obx(() {
final attachments = controller.attachments.listAttachmentsDisplayedOutSide; final attachments = controller.attachments.listAttachmentsDisplayedOutSide;
if (attachments.isNotEmpty) { if (attachments.isNotEmpty) {
@@ -432,7 +437,7 @@ class EmailView extends GetWidget<SingleEmailController> {
EmailActionType.moveToSpam, EmailActionType.moveToSpam,
if (presentationEmail.from?.isNotEmpty == true) if (presentationEmail.from?.isNotEmpty == true)
EmailActionType.createRule, EmailActionType.createRule,
if (controller.emailUnsubscribe.value != null) if (!presentationEmail.isSubscribed && controller.emailUnsubscribe.value != null)
EmailActionType.unsubscribe EmailActionType.unsubscribe
]; ];
@@ -21,6 +21,7 @@ class ComposerArguments extends RouterArguments {
final String? body; final String? body;
final MessageIdsHeaderValue? messageId; final MessageIdsHeaderValue? messageId;
final MessageIdsHeaderValue? references; final MessageIdsHeaderValue? references;
final EmailId? previousEmailId;
ComposerArguments({ ComposerArguments({
this.emailActionType = EmailActionType.compose, this.emailActionType = EmailActionType.compose,
@@ -35,6 +36,7 @@ class ComposerArguments extends RouterArguments {
this.body, this.body,
this.messageId, this.messageId,
this.references, this.references,
this.previousEmailId,
}); });
factory ComposerArguments.fromSendingEmail(SendingEmail sendingEmail) => factory ComposerArguments.fromSendingEmail(SendingEmail sendingEmail) =>
@@ -139,12 +141,18 @@ class ComposerArguments extends RouterArguments {
? SendingEmailActionType.edit ? SendingEmailActionType.edit
: SendingEmailActionType.create; : SendingEmailActionType.create;
factory ComposerArguments.fromUnsubscribeMailtoLink({EmailAddress? emailAddress, String? subject, String? body}) => factory ComposerArguments.fromUnsubscribeMailtoLink({
EmailAddress? emailAddress,
String? subject,
String? body,
EmailId? previousEmailId
}) =>
ComposerArguments( ComposerArguments(
emailActionType: EmailActionType.composeFromUnsubscribeMailtoLink, emailActionType: EmailActionType.composeFromUnsubscribeMailtoLink,
emailAddress: emailAddress, emailAddress: emailAddress,
subject: subject, subject: subject,
body: body, body: body,
previousEmailId: previousEmailId,
); );
@@ -63,7 +63,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
openEmailAddressDetailAction: openEmailAddressDetailAction, openEmailAddressDetailAction: openEmailAddressDetailAction,
) )
)), )),
if (emailUnsubscribe != null && !responsiveUtils.isPortraitMobile(context)) if (!emailSelected.isSubscribed && emailUnsubscribe != null && !responsiveUtils.isPortraitMobile(context))
TMailButtonWidget.fromText( TMailButtonWidget.fromText(
text: AppLocalizations.of(context).unsubscribe, text: AppLocalizations.of(context).unsubscribe,
textStyle: const TextStyle( textStyle: const TextStyle(
@@ -0,0 +1,36 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:flutter/material.dart';
import 'package:model/email/presentation_email.dart';
import 'package:tmail_ui_user/features/email/presentation/model/email_unsubscribe.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class MailUnsubscribedBanner extends StatelessWidget {
final PresentationEmail? presentationEmail;
final EmailUnsubscribe? emailUnsubscribe;
const MailUnsubscribedBanner({
super.key,
required this.presentationEmail,
this.emailUnsubscribe
});
@override
Widget build(BuildContext context) {
if (presentationEmail?.isSubscribed == true && emailUnsubscribe == null) {
return Padding(
padding: const EdgeInsetsDirectional.only(bottom: 16, start: 20, end: 20),
child: Text(
AppLocalizations.of(context).mailUnsubscribedMessage(presentationEmail?.firstEmailAddressInFrom ?? ''),
style: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 15,
color: AppColor.labelColor
),
),
);
} else {
return const SizedBox.shrink();
}
}
}
@@ -24,6 +24,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/delete_multiple_ema
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_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/mark_as_star_email_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/unsubscribe_email_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/controller/email_supervisor_controller.dart'; import 'package:tmail_ui_user/features/email/presentation/controller/email_supervisor_controller.dart';
import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart'; import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart';
import 'package:tmail_ui_user/features/email/presentation/bindings/email_bindings.dart'; import 'package:tmail_ui_user/features/email/presentation/bindings/email_bindings.dart';
@@ -165,6 +166,7 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<SaveEmailAsDraftsInteractor>(), Get.find<SaveEmailAsDraftsInteractor>(),
Get.find<UpdateEmailDraftsInteractor>(), Get.find<UpdateEmailDraftsInteractor>(),
Get.find<DeleteSendingEmailInteractor>(), Get.find<DeleteSendingEmailInteractor>(),
Get.find<UnsubscribeEmailInteractor>(),
)); ));
Get.put(AdvancedFilterController()); Get.put(AdvancedFilterController());
} }
@@ -306,6 +308,7 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<EmailRepository>(), Get.find<EmailRepository>(),
Get.find<MailboxRepository>() Get.find<MailboxRepository>()
)); ));
Get.lazyPut(() => UnsubscribeEmailInteractor(Get.find<EmailRepository>()));
} }
@override @override
@@ -49,11 +49,13 @@ import 'package:tmail_ui_user/features/email/domain/state/delete_sending_email_s
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_read_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/store_sending_email_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/store_sending_email_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/unsubscribe_email_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/delete_email_permanently_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/delete_email_permanently_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/delete_multiple_emails_permanently_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/delete_multiple_emails_permanently_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_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/mark_as_star_email_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/unsubscribe_email_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart'; import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.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/email/presentation/utils/email_utils.dart';
@@ -174,6 +176,7 @@ class MailboxDashBoardController extends ReloadableController {
final SaveEmailAsDraftsInteractor _saveEmailAsDraftsInteractor; final SaveEmailAsDraftsInteractor _saveEmailAsDraftsInteractor;
final UpdateEmailDraftsInteractor _updateEmailDraftsInteractor; final UpdateEmailDraftsInteractor _updateEmailDraftsInteractor;
final DeleteSendingEmailInteractor _deleteSendingEmailInteractor; final DeleteSendingEmailInteractor _deleteSendingEmailInteractor;
final UnsubscribeEmailInteractor _unsubscribeEmailInteractor;
GetAllVacationInteractor? _getAllVacationInteractor; GetAllVacationInteractor? _getAllVacationInteractor;
UpdateVacationInteractor? _updateVacationInteractor; UpdateVacationInteractor? _updateVacationInteractor;
@@ -251,6 +254,7 @@ class MailboxDashBoardController extends ReloadableController {
this._saveEmailAsDraftsInteractor, this._saveEmailAsDraftsInteractor,
this._updateEmailDraftsInteractor, this._updateEmailDraftsInteractor,
this._deleteSendingEmailInteractor, this._deleteSendingEmailInteractor,
this._unsubscribeEmailInteractor,
); );
@override @override
@@ -343,6 +347,8 @@ class MailboxDashBoardController extends ReloadableController {
_markAsReadEmailSuccess(success); _markAsReadEmailSuccess(success);
} else if (success is DeleteSendingEmailSuccess) { } else if (success is DeleteSendingEmailSuccess) {
getAllSendingEmails(); getAllSendingEmails();
} else if (success is UnsubscribeEmailSuccess) {
_handleUnsubscribeMailSuccess(success.newEmail);
} }
} }
@@ -2123,14 +2129,14 @@ class MailboxDashBoardController extends ReloadableController {
void _handleSendEmailSuccess(SendEmailSuccess success) { void _handleSendEmailSuccess(SendEmailSuccess success) {
if (PlatformInfo.isIOS && if (PlatformInfo.isIOS &&
success.storedSendingId != null && success.emailRequest.storedSendingId != null &&
accountId.value != null && accountId.value != null &&
sessionCurrent != null sessionCurrent != null
) { ) {
consumeState(_deleteSendingEmailInteractor.execute( consumeState(_deleteSendingEmailInteractor.execute(
accountId.value!, accountId.value!,
sessionCurrent!.username, sessionCurrent!.username,
success.storedSendingId! success.emailRequest.storedSendingId!
)); ));
} }
if (currentOverlayContext != null && currentContext != null) { if (currentOverlayContext != null && currentContext != null) {
@@ -2140,6 +2146,11 @@ class MailboxDashBoardController extends ReloadableController {
leadingSVGIcon: imagePaths.icSendSuccessToast leadingSVGIcon: imagePaths.icSendSuccessToast
); );
} }
if (success.emailRequest.emailActionType == EmailActionType.composeFromUnsubscribeMailtoLink &&
success.emailRequest.previousEmailId != null) {
unsubscribeMail(success.emailRequest.previousEmailId!);
}
} }
void _updateSendingStateWhenSendEmailFailureOnIOS(SendEmailFailure failure) { void _updateSendingStateWhenSendEmailFailureOnIOS(SendEmailFailure failure) {
@@ -2192,6 +2203,27 @@ class MailboxDashBoardController extends ReloadableController {
dispatchAction(SearchEmailByFromFieldsAction(emailAddress)); dispatchAction(SearchEmailByFromFieldsAction(emailAddress));
} }
void unsubscribeMail(EmailId emailId) {
if (accountId.value != null && sessionCurrent != null) {
consumeState(
_unsubscribeEmailInteractor.execute(
sessionCurrent!,
accountId.value!,
emailId
)
);
}
}
void _handleUnsubscribeMailSuccess(Email email) {
if (currentContext != null && currentOverlayContext != null) {
appToast.showToastSuccessMessage(
currentOverlayContext!,
AppLocalizations.of(currentContext!).unsubscribedFromThisMailingList);
}
setSelectedEmail(email.toPresentationEmail());
}
@override @override
void onClose() { void onClose() {
_emailReceiveManager.closeEmailReceiveManagerStream(); _emailReceiveManager.closeEmailReceiveManagerStream();
@@ -37,6 +37,7 @@ import 'package:tmail_ui_user/features/email/domain/state/delete_multiple_emails
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_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/state/mark_as_email_star_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/unsubscribe_email_state.dart';
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart'; import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.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/presentation/model/mailbox_actions.dart';
@@ -209,7 +210,8 @@ class SearchEmailController extends BaseController
success is EmptyTrashFolderSuccess || success is EmptyTrashFolderSuccess ||
success is EmptySpamFolderSuccess || success is EmptySpamFolderSuccess ||
success is DeleteMultipleEmailsPermanentlyAllSuccess || success is DeleteMultipleEmailsPermanentlyAllSuccess ||
success is DeleteMultipleEmailsPermanentlyHasSomeEmailFailure success is DeleteMultipleEmailsPermanentlyHasSomeEmailFailure ||
success is UnsubscribeEmailSuccess
) { ) {
_refreshEmailChanges(); _refreshEmailChanges();
} }
@@ -28,6 +28,7 @@ import 'package:tmail_ui_user/features/email/domain/state/delete_multiple_emails
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_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/state/mark_as_email_star_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/unsubscribe_email_state.dart';
import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart'; import 'package:tmail_ui_user/features/email/presentation/action/email_ui_action.dart';
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart'; import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/mark_as_mailbox_read_state.dart';
@@ -348,6 +349,8 @@ class ThreadController extends BaseController with EmailActionController {
_refreshEmailChanges(currentEmailState: success.currentEmailState); _refreshEmailChanges(currentEmailState: success.currentEmailState);
} else if (success is EmptyTrashFolderSuccess || success is EmptySpamFolderSuccess) { } else if (success is EmptyTrashFolderSuccess || success is EmptySpamFolderSuccess) {
refreshAllEmail(); refreshAllEmail();
} else if (success is UnsubscribeEmailSuccess) {
_refreshEmailChanges(currentEmailState: success.currentEmailState);
} }
}); });
}); });
+11 -1
View File
@@ -1,5 +1,5 @@
{ {
"@@last_modified": "2023-11-16T00:29:04.650547", "@@last_modified": "2023-11-16T12:39:33.304952",
"initializing_data": "Initializing data...", "initializing_data": "Initializing data...",
"@initializing_data": { "@initializing_data": {
"type": "text", "type": "text",
@@ -3517,5 +3517,15 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"mailUnsubscribedMessage": "You unsubscribe from {senderName}",
"@mailUnsubscribedMessage": {
"type": "text",
"placeholders_order": [
"senderName"
],
"placeholders": {
"senderName": {}
}
} }
} }
@@ -3652,4 +3652,12 @@ class AppLocalizations {
name: 'unsubscribedFromThisMailingList', name: 'unsubscribedFromThisMailingList',
); );
} }
String mailUnsubscribedMessage(String senderName) {
return Intl.message(
'You unsubscribe from $senderName',
name: 'mailUnsubscribedMessage',
args: [senderName]
);
}
} }
+3
View File
@@ -13,6 +13,7 @@ import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/email/email_content.dart'; import 'package:model/email/email_content.dart';
import 'package:model/extensions/email_address_extension.dart'; import 'package:model/extensions/email_address_extension.dart';
import 'package:model/extensions/keyword_identifier_extension.dart';
import 'package:model/extensions/media_type_nullable_extension.dart'; import 'package:model/extensions/media_type_nullable_extension.dart';
import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:model/mailbox/select_mode.dart'; import 'package:model/mailbox/select_mode.dart';
@@ -110,6 +111,8 @@ class PresentationEmail with EquatableMixin {
bool get isForwarded => keywords?.containsKey(KeyWordIdentifier.emailForwarded) == true; bool get isForwarded => keywords?.containsKey(KeyWordIdentifier.emailForwarded) == true;
bool get isSubscribed => keywords?.containsKey(KeyWordIdentifierExtension.unsubscribeMail) == true;
bool get isAnsweredAndForwarded => isAnswered && isForwarded; bool get isAnsweredAndForwarded => isAnswered && isForwarded;
bool get withAttachments => hasAttachment == true; bool get withAttachments => hasAttachment == true;
@@ -25,6 +25,8 @@ extension EmailExtension on Email {
bool get isDraft => keywords?.containsKey(KeyWordIdentifier.emailDraft) == true; bool get isDraft => keywords?.containsKey(KeyWordIdentifier.emailDraft) == true;
bool get isUnsubscribed => keywords?.containsKey(KeyWordIdentifierExtension.unsubscribeMail) == true;
bool get withAttachments => hasAttachment == true; bool get withAttachments => hasAttachment == true;
String get listUnsubscribe { String get listUnsubscribe {