diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index 713283b1c..b4196c76c 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -1285,4 +1285,18 @@ class SingleEmailController extends BaseController with AppLoaderMixin { void _enableScrollPageView() { emailSupervisorController.scrollPhysicsPageView.value = null; } + + void openNewTabAction(String link) { + AppUtils.launchLink(link); + } + + void openNewComposerAction(String mailTo) { + final emailAddress = EmailAddress(mailTo, mailTo); + final arguments = ComposerArguments( + emailActionType: EmailActionType.composeFromEmailAddress, + emailAddress: emailAddress, + mailboxRole: mailboxDashBoardController.selectedMailbox.value?.role + ); + mailboxDashBoardController.goToComposer(arguments); + } } \ No newline at end of file diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart index 162b6c09b..2c0dc20e7 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -298,13 +298,21 @@ class EmailView extends GetWidget with AppLoaderMixin { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - CalendarEventInformationWidget(calendarEvent: calendarEvent), + CalendarEventInformationWidget( + calendarEvent: calendarEvent, + onOpenComposerAction: controller.openNewComposerAction, + onOpenNewTabAction: controller.openNewTabAction, + ), if (calendarEvent.getTitleEventAction(context, listEmailAddressSender).isNotEmpty) CalendarEventActionBannerWidget( calendarEvent: calendarEvent, listEmailAddressSender: listEmailAddressSender ), - CalendarEventDetailWidget(calendarEvent: calendarEvent), + CalendarEventDetailWidget( + calendarEvent: calendarEvent, + onOpenComposerAction: controller.openNewComposerAction, + onOpenNewTabAction: controller.openNewTabAction, + ), ], ); } else { diff --git a/lib/features/email/presentation/widgets/calendar_event/calendar_event_detail_widget.dart b/lib/features/email/presentation/widgets/calendar_event/calendar_event_detail_widget.dart index 0d6c39bf2..d54ec519c 100644 --- a/lib/features/email/presentation/widgets/calendar_event/calendar_event_detail_widget.dart +++ b/lib/features/email/presentation/widgets/calendar_event/calendar_event_detail_widget.dart @@ -13,10 +13,14 @@ import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event class CalendarEventDetailWidget extends StatelessWidget { final CalendarEvent calendarEvent; + final OnOpenNewTabAction? onOpenNewTabAction; + final OnOpenComposerAction? onOpenComposerAction; const CalendarEventDetailWidget({ super.key, - required this.calendarEvent + required this.calendarEvent, + this.onOpenNewTabAction, + this.onOpenComposerAction, }); @override @@ -61,7 +65,11 @@ class CalendarEventDetailWidget extends StatelessWidget { if (calendarEvent.location?.isNotEmpty == true) Padding( padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding), - child: EventLocationDetailWidget(locationEvent: calendarEvent.location!), + child: EventLocationDetailWidget( + locationEvent: calendarEvent.location!, + onOpenComposerAction: onOpenComposerAction, + onOpenNewTabAction: onOpenNewTabAction, + ), ), if (calendarEvent.participants?.isNotEmpty == true && calendarEvent.organizer != null) Padding( diff --git a/lib/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart b/lib/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart index ed7490a1b..f19035355 100644 --- a/lib/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart +++ b/lib/features/email/presentation/widgets/calendar_event/calendar_event_information_widget.dart @@ -8,6 +8,7 @@ import 'package:tmail_ui_user/features/email/presentation/extensions/calendar_ev import 'package:tmail_ui_user/features/email/presentation/styles/calendar_event_information_widget_styles.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_attendee_information_widget.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/calendar_date_icon_widget.dart'; +import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_location_detail_widget.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_location_information_widget.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_time_information_widget.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_title_widget.dart'; @@ -16,10 +17,14 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class CalendarEventInformationWidget extends StatelessWidget { final CalendarEvent calendarEvent; + final OnOpenNewTabAction? onOpenNewTabAction; + final OnOpenComposerAction? onOpenComposerAction; const CalendarEventInformationWidget({ super.key, - required this.calendarEvent + required this.calendarEvent, + this.onOpenNewTabAction, + this.onOpenComposerAction, }); @override @@ -93,7 +98,11 @@ class CalendarEventInformationWidget extends StatelessWidget { if (calendarEvent.location?.isNotEmpty == true) Padding( padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding), - child: EventLocationInformationWidget(locationEvent: calendarEvent.location!), + child: EventLocationInformationWidget( + locationEvent: calendarEvent.location!, + onOpenComposerAction: onOpenComposerAction, + onOpenNewTabAction: onOpenNewTabAction, + ), ), if (calendarEvent.participants?.isNotEmpty == true && calendarEvent.organizer != null) Padding( @@ -158,7 +167,11 @@ class CalendarEventInformationWidget extends StatelessWidget { if (calendarEvent.location?.isNotEmpty == true) Padding( padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding), - child: EventLocationInformationWidget(locationEvent: calendarEvent.location!), + child: EventLocationInformationWidget( + locationEvent: calendarEvent.location!, + onOpenComposerAction: onOpenComposerAction, + onOpenNewTabAction: onOpenNewTabAction, + ), ), if (calendarEvent.participants?.isNotEmpty == true && calendarEvent.organizer != null) Padding( diff --git a/lib/features/email/presentation/widgets/calendar_event/event_location_detail_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_location_detail_widget.dart index 36b046848..36d79e84a 100644 --- a/lib/features/email/presentation/widgets/calendar_event/event_location_detail_widget.dart +++ b/lib/features/email/presentation/widgets/calendar_event/event_location_detail_widget.dart @@ -1,15 +1,24 @@ +import 'package:core/utils/app_logger.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:tmail_ui_user/features/email/presentation/styles/event_location_detail_widget_styles.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; +typedef OnOpenNewTabAction = void Function(String link); +typedef OnOpenComposerAction = void Function(String emailAddress); + class EventLocationDetailWidget extends StatelessWidget { final String locationEvent; + final OnOpenNewTabAction? onOpenNewTabAction; + final OnOpenComposerAction? onOpenComposerAction; const EventLocationDetailWidget({ super.key, - required this.locationEvent + required this.locationEvent, + this.onOpenNewTabAction, + this.onOpenComposerAction, }); @override @@ -28,13 +37,30 @@ class EventLocationDetailWidget extends StatelessWidget { ), ), ), - Expanded(child: Text( - locationEvent, + Expanded(child: Linkify( + onOpen: (element) { + log('EventLocationDetailWidget::build:element: $element'); + if (element is UrlElement) { + onOpenNewTabAction?.call(element.url); + } else if (element is EmailElement) { + onOpenComposerAction?.call(element.emailAddress); + } + }, + text: locationEvent, + linkifiers: const [ + EmailLinkifier(), + UrlLinkifier() + ], style: const TextStyle( fontSize: EventLocationDetailWidgetStyles.textSize, fontWeight: FontWeight.w500, color: EventLocationDetailWidgetStyles.valueColor ), + options: const LinkifyOptions( + removeWww: true, + looseUrl: true, + defaultToHttps: true + ), )) ], ); diff --git a/lib/features/email/presentation/widgets/calendar_event/event_location_information_widget.dart b/lib/features/email/presentation/widgets/calendar_event/event_location_information_widget.dart index 3aa35ff05..5574e99c4 100644 --- a/lib/features/email/presentation/widgets/calendar_event/event_location_information_widget.dart +++ b/lib/features/email/presentation/widgets/calendar_event/event_location_information_widget.dart @@ -1,23 +1,26 @@ -import 'package:core/presentation/utils/responsive_utils.dart'; -import 'package:core/presentation/utils/style_utils.dart'; +import 'package:core/utils/app_logger.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:tmail_ui_user/features/email/presentation/styles/event_location_information_widget_styles.dart'; +import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_location_detail_widget.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class EventLocationInformationWidget extends StatelessWidget { final String locationEvent; + final OnOpenNewTabAction? onOpenNewTabAction; + final OnOpenComposerAction? onOpenComposerAction; const EventLocationInformationWidget({ super.key, - required this.locationEvent + required this.locationEvent, + this.onOpenNewTabAction, + this.onOpenComposerAction, }); @override Widget build(BuildContext context) { - final responsiveUtils = Get.find(); return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -32,16 +35,30 @@ class EventLocationInformationWidget extends StatelessWidget { ), ), ), - Expanded(child: Text( - locationEvent, - overflow: responsiveUtils.isPortraitMobile(context) ? null : CommonTextStyle.defaultTextOverFlow, - softWrap: responsiveUtils.isPortraitMobile(context) ? null : CommonTextStyle.defaultSoftWrap, - maxLines: responsiveUtils.isPortraitMobile(context) ? null : 1, + Expanded(child: Linkify( + onOpen: (element) { + log('EventLocationInformationWidget::build:element: $element'); + if (element is UrlElement) { + onOpenNewTabAction?.call(element.url); + } else if (element is EmailElement) { + onOpenComposerAction?.call(element.emailAddress); + } + }, + text: locationEvent, + linkifiers: const [ + EmailLinkifier(), + UrlLinkifier() + ], style: const TextStyle( fontSize: EventLocationInformationWidgetStyles.textSize, fontWeight: FontWeight.w500, color: EventLocationInformationWidgetStyles.valueColor ), + options: const LinkifyOptions( + removeWww: true, + looseUrl: true, + defaultToHttps: true + ), )) ], ); diff --git a/pubspec.lock b/pubspec.lock index c184debf4..104a98197 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -711,6 +711,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.12.0" + flutter_linkify: + dependency: "direct main" + description: + name: flutter_linkify + sha256: "74669e06a8f358fee4512b4320c0b80e51cffc496607931de68d28f099254073" + url: "https://pub.dev" + source: hosted + version: "6.0.0" flutter_lints: dependency: "direct dev" description: diff --git a/pubspec.yaml b/pubspec.yaml index e7484a569..30ee10fc8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -205,6 +205,8 @@ dependencies: date_format: 2.0.7 + flutter_linkify: 6.0.0 + dev_dependencies: flutter_test: sdk: flutter