diff --git a/core/lib/data/network/config/service_path.dart b/core/lib/data/network/config/service_path.dart index 68163010a..0ff7ccf72 100644 --- a/core/lib/data/network/config/service_path.dart +++ b/core/lib/data/network/config/service_path.dart @@ -1,6 +1,11 @@ -class ServicePath { +import 'package:equatable/equatable.dart'; + +class ServicePath with EquatableMixin { final String path; ServicePath(this.path); + + @override + List get props => [path]; } \ No newline at end of file diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 5efb203ef..51b2ed04d 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -489,6 +489,9 @@ class ComposerController extends BaseController { isInitialRecipient.value = true; toAddressExpandMode.value = ExpandMode.COLLAPSE; } + if (arguments.body?.isNotEmpty == true) { + _getEmailContentFromMailtoUri(arguments.body!); + } _updateStatusEmailSendButton(); break; case EmailActionType.reply: @@ -524,6 +527,21 @@ class ComposerController extends BaseController { _initAttachments(arguments.attachments ?? []); _getEmailContentFromSessionStorageBrowser(arguments.emailContents!); break; + case EmailActionType.composeFromUnsubscribeMailtoLink: + if (arguments.subject != null) { + setSubjectEmail(arguments.subject!); + subjectEmailInputController.text = arguments.subject!; + } + if (arguments.emailAddress != null) { + listToEmailAddress.add(arguments.emailAddress!); + isInitialRecipient.value = true; + toAddressExpandMode.value = ExpandMode.COLLAPSE; + } + if (arguments.body?.isNotEmpty == true) { + _getEmailContentFromUnsubscribeMailtoLink(arguments.body!); + } + _updateStatusEmailSendButton(); + break; default: break; } @@ -1422,6 +1440,26 @@ class ComposerController extends BaseController { )); } + void _getEmailContentFromMailtoUri(String content) { + log('ComposerController::_getEmailContentFromMailtoUri:content: $content'); + consumeState(Stream.value( + Right(GetEmailContentSuccess( + htmlEmailContent: content, + attachments: [], + )) + )); + } + + void _getEmailContentFromUnsubscribeMailtoLink(String content) { + log('ComposerController::_getEmailContentFromUnsubscribeMailtoLink:content: $content'); + consumeState(Stream.value( + Right(GetEmailContentSuccess( + htmlEmailContent: content, + attachments: [], + )) + )); + } + void _getEmailContentFromEmailId({required EmailId emailId, bool isDraftEmail = false}) { final session = mailboxDashBoardController.sessionCurrent; final accountId = mailboxDashBoardController.accountId.value; diff --git a/lib/features/composer/presentation/view/mobile/mobile_editor_view.dart b/lib/features/composer/presentation/view/mobile/mobile_editor_view.dart index c3b106a31..b425d86ca 100644 --- a/lib/features/composer/presentation/view/mobile/mobile_editor_view.dart +++ b/lib/features/composer/presentation/view/mobile/mobile_editor_view.dart @@ -47,6 +47,8 @@ class MobileEditorView extends StatelessWidget with EditorViewMixin { case EmailActionType.editSendingEmail: case EmailActionType.composeFromContentShared: case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromMailtoUri: + case EmailActionType.composeFromUnsubscribeMailtoLink: if (contentViewState == null) { return const SizedBox.shrink(); } diff --git a/lib/features/composer/presentation/view/web/web_editor_view.dart b/lib/features/composer/presentation/view/web/web_editor_view.dart index 0cf8bd6df..e9d2826cc 100644 --- a/lib/features/composer/presentation/view/web/web_editor_view.dart +++ b/lib/features/composer/presentation/view/web/web_editor_view.dart @@ -81,6 +81,8 @@ class WebEditorView extends StatelessWidget with EditorViewMixin { case EmailActionType.editSendingEmail: case EmailActionType.composeFromContentShared: case EmailActionType.reopenComposerBrowser: + case EmailActionType.composeFromUnsubscribeMailtoLink: + case EmailActionType.composeFromMailtoUri: if (contentViewState == null) { return const SizedBox.shrink(); } diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index b64f5b4c8..e01462beb 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -1407,6 +1407,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin { onConfirmAction: () { if (emailUnsubscribe.value?.httpLinks.isNotEmpty == true) { _handleUnsubscribeMailByHttpsLink(context, emailUnsubscribe.value!.httpLinks); + } else if (emailUnsubscribe.value?.mailtoLinks.isNotEmpty == true) { + _handleUnsubscribeMailByMailtoLink(context, emailUnsubscribe.value!.mailtoLinks); } }, showAsBottomSheet: true, @@ -1441,4 +1443,16 @@ class SingleEmailController extends BaseController with AppLoaderMixin { AppLocalizations.of(context).unsubscribedFromThisMailingList); } } + + void _handleUnsubscribeMailByMailtoLink(BuildContext context, List mailtoLinks) { + log('SingleEmailController::_handleUnsubscribeMailByMailtoLink:mailtoLinks: $mailtoLinks'); + final navigationRouter = RouteUtils.generateNavigationRouterFromMailtoLink(mailtoLinks.first); + mailboxDashBoardController.goToComposer( + ComposerArguments.fromUnsubscribeMailtoLink( + emailAddress: navigationRouter.emailAddress, + subject: navigationRouter.subject, + body: navigationRouter.body + ) + ); + } } \ No newline at end of file diff --git a/lib/features/email/presentation/model/composer_arguments.dart b/lib/features/email/presentation/model/composer_arguments.dart index 4f6b969e9..4ed2aaad7 100644 --- a/lib/features/email/presentation/model/composer_arguments.dart +++ b/lib/features/email/presentation/model/composer_arguments.dart @@ -18,6 +18,7 @@ class ComposerArguments extends RouterArguments { final Role? mailboxRole; final SendingEmail? sendingEmail; final String? subject; + final String? body; final MessageIdsHeaderValue? messageId; final MessageIdsHeaderValue? references; @@ -31,6 +32,7 @@ class ComposerArguments extends RouterArguments { this.listSharedMediaFile, this.sendingEmail, this.subject, + this.body, this.messageId, this.references, }); @@ -59,11 +61,12 @@ class ComposerArguments extends RouterArguments { emailAddress: emailAddress ); - factory ComposerArguments.fromMailtoUri({EmailAddress? emailAddress, String? subject}) => + factory ComposerArguments.fromMailtoUri({EmailAddress? emailAddress, String? subject, String? body}) => ComposerArguments( emailActionType: EmailActionType.composeFromMailtoUri, emailAddress: emailAddress, subject: subject, + body: body, ); factory ComposerArguments.editDraftEmail(PresentationEmail presentationEmail) => @@ -136,6 +139,15 @@ class ComposerArguments extends RouterArguments { ? SendingEmailActionType.edit : SendingEmailActionType.create; + factory ComposerArguments.fromUnsubscribeMailtoLink({EmailAddress? emailAddress, String? subject, String? body}) => + ComposerArguments( + emailActionType: EmailActionType.composeFromUnsubscribeMailtoLink, + emailAddress: emailAddress, + subject: subject, + body: body, + ); + + @override List get props => [ emailActionType, @@ -147,6 +159,7 @@ class ComposerArguments extends RouterArguments { listSharedMediaFile, sendingEmail, subject, + body, messageId, references, ]; diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index fd312b2d5..58312d340 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -425,7 +425,8 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM mailboxDashBoardController.goToComposer( ComposerArguments.fromMailtoUri( emailAddress: navigationRouter?.emailAddress, - subject: navigationRouter?.subject + subject: navigationRouter?.subject, + body: navigationRouter?.body ) ); } diff --git a/lib/main/routes/navigation_router.dart b/lib/main/routes/navigation_router.dart index b87041721..952325e00 100644 --- a/lib/main/routes/navigation_router.dart +++ b/lib/main/routes/navigation_router.dart @@ -18,6 +18,7 @@ class NavigationRouter with EquatableMixin { final String? routeName; final EmailAddress? emailAddress; final String? subject; + final String? body; NavigationRouter({ this.emailId, @@ -27,6 +28,7 @@ class NavigationRouter with EquatableMixin { this.routeName, this.emailAddress, this.subject, + this.body, }); factory NavigationRouter.initial() => NavigationRouter(); @@ -40,5 +42,6 @@ class NavigationRouter with EquatableMixin { routeName, emailAddress, subject, + body, ]; } \ No newline at end of file diff --git a/lib/main/routes/route_utils.dart b/lib/main/routes/route_utils.dart index 9bf29a84c..758a2b299 100644 --- a/lib/main/routes/route_utils.dart +++ b/lib/main/routes/route_utils.dart @@ -23,6 +23,7 @@ abstract class RouteUtils { static const String paramRouteName = 'routeName'; static const String paramMailtoAddress = 'mailtoAddress'; static const String paramSubject = 'subject'; + static const String paramBody = 'body'; static const String mailtoPrefix = 'mailto:'; @@ -76,6 +77,7 @@ abstract class RouteUtils { final routeName = parameters[paramRouteName]; final mailtoAddress = parameters[paramMailtoAddress]; final subject = parameters[paramSubject]; + final body = parameters[paramBody]; final emailId = idParam != null ? EmailId(Id(idParam)) : null; final mailboxId = contextPram != null ? MailboxId(Id(contextPram)) : null; @@ -95,6 +97,7 @@ abstract class RouteUtils { routeName: routeName, emailAddress: emailAddress, subject: subject, + body: body, ); } @@ -121,6 +124,9 @@ abstract class RouteUtils { if (mapQueryParam.containsKey(paramSubject)) { mapMailto[paramSubject] = mapQueryParam[paramSubject]; } + if (mapQueryParam.containsKey(paramBody)) { + mapMailto[paramBody] = mapQueryParam[paramBody]; + } } else if (mailtoUri != null) { final mailtoUrlDecoded = Uri.decodeFull(mailtoUri); mapMailto[paramMailtoAddress] = mailtoUrlDecoded; @@ -130,4 +136,11 @@ abstract class RouteUtils { log('RouteUtils::parseMapMailtoFromUri:mapMailto: $mapMailto'); return mapMailto; } + + static NavigationRouter generateNavigationRouterFromMailtoLink(String mailtoLink) { + final mailtoMap = parseMapMailtoFromUri(mailtoLink); + final navigationRouter = parsingRouteParametersToNavigationRouter(mailtoMap); + log('RouteUtils::generateNavigationRouterFromMailtoLink:navigationRouter: $navigationRouter'); + return navigationRouter; + } } \ No newline at end of file diff --git a/model/lib/email/email_action_type.dart b/model/lib/email/email_action_type.dart index 921bdceb7..b52b76ef1 100644 --- a/model/lib/email/email_action_type.dart +++ b/model/lib/email/email_action_type.dart @@ -25,4 +25,5 @@ enum EmailActionType { openInNewTab, createRule, unsubscribe, + composeFromUnsubscribeMailtoLink, } \ No newline at end of file