diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 4c27bc4ae..6383e8ba8 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -440,14 +440,16 @@ class ComposerController extends BaseController { toAddressExpandMode.value = ExpandMode.COLLAPSE; _updateStatusEmailSendButton(); break; - case EmailActionType.composeFromMailtoURL: - if (GetUtils.isEmail(arguments.uri ?? '')) { - listToEmailAddress.add(EmailAddress(null, arguments.uri)); - } else { - listToEmailAddress.add(EmailAddress(null, 'invalid')); + case EmailActionType.composeFromMailtoUri: + 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; } - isInitialRecipient.value = true; - toAddressExpandMode.value = ExpandMode.COLLAPSE; _updateStatusEmailSendButton(); break; case EmailActionType.reply: diff --git a/lib/features/email/presentation/model/composer_arguments.dart b/lib/features/email/presentation/model/composer_arguments.dart index 785982708..52d0a0e4a 100644 --- a/lib/features/email/presentation/model/composer_arguments.dart +++ b/lib/features/email/presentation/model/composer_arguments.dart @@ -16,7 +16,7 @@ class ComposerArguments extends RouterArguments { final List? attachments; final Role? mailboxRole; final SendingEmail? sendingEmail; - final String? uri; + final String? subject; final MessageIdsHeaderValue? messageId; final MessageIdsHeaderValue? references; @@ -29,7 +29,7 @@ class ComposerArguments extends RouterArguments { this.emailAddress, this.listSharedMediaFile, this.sendingEmail, - this.uri, + this.subject, this.messageId, this.references, }); @@ -58,10 +58,11 @@ class ComposerArguments extends RouterArguments { emailAddress: emailAddress ); - factory ComposerArguments.fromMailtoURL(String? uri) => + factory ComposerArguments.fromMailtoUri({EmailAddress? emailAddress, String? subject}) => ComposerArguments( - emailActionType: EmailActionType.composeFromMailtoURL, - uri: uri + emailActionType: EmailActionType.composeFromMailtoUri, + emailAddress: emailAddress, + subject: subject, ); factory ComposerArguments.editDraftEmail(PresentationEmail presentationEmail) => @@ -140,7 +141,7 @@ class ComposerArguments extends RouterArguments { emailAddress, listSharedMediaFile, sendingEmail, - uri, + subject, messageId, references, ]; diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 6e2f98019..f1025c46f 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -405,7 +405,10 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM if (isHasDataFromRoute) { if (isRedirectToMailtoURL) { mailboxDashBoardController.goToComposer( - ComposerArguments.fromMailtoURL(navigationRouter?.emailAddress) + ComposerArguments.fromMailtoUri( + emailAddress: navigationRouter?.emailAddress, + subject: navigationRouter?.subject + ) ); } diff --git a/lib/features/mailto/presentation/mailto_url_controller.dart b/lib/features/mailto/presentation/mailto_url_controller.dart index ec90fc723..9953d08aa 100644 --- a/lib/features/mailto/presentation/mailto_url_controller.dart +++ b/lib/features/mailto/presentation/mailto_url_controller.dart @@ -39,7 +39,7 @@ class MailtoUrlController extends ReloadableController { if (parameters.containsKey('uri')) { final mailtoArgument = MailtoArguments( session: session, - emailAddress: parameters['uri'] + mailtoUri: parameters['uri'] ); popAndPush( RouteUtils.generateNavigationRoute( diff --git a/lib/features/mailto/presentation/model/mailto_arguments.dart b/lib/features/mailto/presentation/model/mailto_arguments.dart index d1294d328..ec7d538e1 100644 --- a/lib/features/mailto/presentation/model/mailto_arguments.dart +++ b/lib/features/mailto/presentation/model/mailto_arguments.dart @@ -1,22 +1,17 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart'; -import 'package:tmail_ui_user/main/routes/app_routes.dart'; +import 'package:tmail_ui_user/main/routes/route_utils.dart'; import 'package:tmail_ui_user/main/routes/router_arguments.dart'; class MailtoArguments extends RouterArguments { final Session session; - final String? emailAddress; + final String? mailtoUri; - MailtoArguments({required this.session, this.emailAddress}); + MailtoArguments({required this.session, this.mailtoUri}); - Map toMapRouter() { - return { - 'routeName': AppRoutes.mailtoURL, - 'emailAddress': emailAddress - }; - } + Map toMapRouter() => RouteUtils.parseMapMailtoFromUri(mailtoUri); @override - List get props => [session, emailAddress]; + List get props => [session, mailtoUri]; } \ No newline at end of file diff --git a/lib/main/routes/navigation_router.dart b/lib/main/routes/navigation_router.dart index bdac232f1..b87041721 100644 --- a/lib/main/routes/navigation_router.dart +++ b/lib/main/routes/navigation_router.dart @@ -1,6 +1,7 @@ import 'package:equatable/equatable.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:tmail_ui_user/features/thread/domain/model/search_query.dart'; @@ -15,7 +16,8 @@ class NavigationRouter with EquatableMixin { final DashboardType dashboardType; final SearchQuery? searchQuery; final String? routeName; - final String? emailAddress; + final EmailAddress? emailAddress; + final String? subject; NavigationRouter({ this.emailId, @@ -24,6 +26,7 @@ class NavigationRouter with EquatableMixin { this.dashboardType = DashboardType.normal, this.routeName, this.emailAddress, + this.subject, }); factory NavigationRouter.initial() => NavigationRouter(); @@ -36,5 +39,6 @@ class NavigationRouter with EquatableMixin { dashboardType, routeName, emailAddress, + subject, ]; } \ No newline at end of file diff --git a/lib/main/routes/route_utils.dart b/lib/main/routes/route_utils.dart index 0b3e9a286..9bf29a84c 100644 --- a/lib/main/routes/route_utils.dart +++ b/lib/main/routes/route_utils.dart @@ -3,16 +3,31 @@ import 'package:core/data/model/query/query_parameter.dart'; import 'package:core/data/network/config/service_path.dart'; import 'package:core/utils/app_logger.dart'; import 'package:core/utils/platform_info.dart'; +import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/core/id.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:tmail_ui_user/features/login/data/extensions/service_path_extension.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; +import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/navigation_router.dart'; import 'package:universal_html/html.dart' as html; abstract class RouteUtils { + static const String paramID = 'id'; + static const String paramType = 'type'; + static const String paramContext = 'context'; + static const String paramQuery = 'q'; + static const String paramRouteName = 'routeName'; + static const String paramMailtoAddress = 'mailtoAddress'; + static const String paramSubject = 'subject'; + + static const String mailtoPrefix = 'mailto:'; + + static const String INVALID_VALUE = 'invalid'; + static String get baseOriginUrl => Uri.base.origin; static String get baseUrl => Uri.base.path; @@ -24,11 +39,11 @@ abstract class RouteUtils { servicePath = servicePath.withPathParameter(router.emailId!.id.value); } servicePath = servicePath.withQueryParameters([ - StringQueryParameter('type', router.dashboardType.name), + StringQueryParameter(paramType, router.dashboardType.name), if (router.mailboxId != null) - StringQueryParameter('context', router.mailboxId!.id.value), + StringQueryParameter(paramContext, router.mailboxId!.id.value), if (router.searchQuery != null) - StringQueryParameter('q', router.searchQuery!.value), + StringQueryParameter(paramQuery, router.searchQuery!.value), ]); return servicePath.path; } else { @@ -43,23 +58,24 @@ abstract class RouteUtils { servicePath = servicePath.withPathParameter(router.emailId!.id.value); } servicePath = servicePath.withQueryParameters([ - StringQueryParameter('type', router.dashboardType.name), + StringQueryParameter(paramType, router.dashboardType.name), if (router.mailboxId != null) - StringQueryParameter('context', router.mailboxId!.id.value), + StringQueryParameter(paramContext, router.mailboxId!.id.value), if (router.searchQuery != null) - StringQueryParameter('q', router.searchQuery!.value), + StringQueryParameter(paramQuery, router.searchQuery!.value), ]); return Uri.parse(servicePath.path); } static NavigationRouter parsingRouteParametersToNavigationRouter(Map parameters) { - final idParam = parameters['id']; - final typeParam = parameters['type']; - final contextPram = parameters['context']; - final queryParam = parameters['q']; - final routeName = parameters['routeName']; - final emailAddress = parameters['emailAddress']; + final idParam = parameters[paramID]; + final typeParam = parameters[paramType]; + final contextPram = parameters[paramContext]; + final queryParam = parameters[paramQuery]; + final routeName = parameters[paramRouteName]; + final mailtoAddress = parameters[paramMailtoAddress]; + final subject = parameters[paramSubject]; final emailId = idParam != null ? EmailId(Id(idParam)) : null; final mailboxId = contextPram != null ? MailboxId(Id(contextPram)) : null; @@ -67,6 +83,9 @@ abstract class RouteUtils { final dashboardType = typeParam == DashboardType.search.name ? DashboardType.search : DashboardType.normal; + final emailAddress = mailtoAddress != null && GetUtils.isEmail(mailtoAddress) + ? EmailAddress(null, mailtoAddress) + : EmailAddress(null, INVALID_VALUE); return NavigationRouter( emailId: emailId, @@ -75,6 +94,7 @@ abstract class RouteUtils { dashboardType: dashboardType, routeName: routeName, emailAddress: emailAddress, + subject: subject, ); } @@ -83,4 +103,31 @@ abstract class RouteUtils { log('RouteUtils::updateRouteOnBrowser(): newRoute: $newRoute'); html.window.history.replaceState(null, title, newRoute.toString()); } + + static Map parseMapMailtoFromUri(String? mailtoUri) { + log('RouteUtils::parseMapMailtoFromUri:mailtoUri: $mailtoUri'); + final mapMailto = { + RouteUtils.paramRouteName: AppRoutes.mailtoURL, + }; + if (mailtoUri?.startsWith(mailtoPrefix) == true) { + final mailtoUrlDecoded = Uri.decodeFull(mailtoUri!); + final uri = Uri.tryParse(mailtoUrlDecoded); + if (uri == null) return mapMailto; + + final mailtoAddress = uri.path; + final mapQueryParam = uri.queryParameters; + + mapMailto[paramMailtoAddress] = mailtoAddress; + if (mapQueryParam.containsKey(paramSubject)) { + mapMailto[paramSubject] = mapQueryParam[paramSubject]; + } + } else if (mailtoUri != null) { + final mailtoUrlDecoded = Uri.decodeFull(mailtoUri); + mapMailto[paramMailtoAddress] = mailtoUrlDecoded; + } else { + mapMailto[paramMailtoAddress] = mailtoUri; + } + log('RouteUtils::parseMapMailtoFromUri:mapMailto: $mapMailto'); + return mapMailto; + } } \ 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 fb13defdf..2ea30b84f 100644 --- a/model/lib/email/email_action_type.dart +++ b/model/lib/email/email_action_type.dart @@ -14,7 +14,7 @@ enum EmailActionType { composeFromContentShared, composeFromFileShared, composeFromEmailAddress, - composeFromMailtoURL, + composeFromMailtoUri, reopenComposerBrowser, moveToTrash, deletePermanently,