TF-2068 Create highlight autolink for event location widget
(cherry picked from commit a77f1d5aa8d440413b141097197f128c75f04588)
This commit is contained in:
@@ -1285,4 +1285,18 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
|||||||
void _enableScrollPageView() {
|
void _enableScrollPageView() {
|
||||||
emailSupervisorController.scrollPhysicsPageView.value = null;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -298,13 +298,21 @@ class EmailView extends GetWidget<SingleEmailController> with AppLoaderMixin {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
CalendarEventInformationWidget(calendarEvent: calendarEvent),
|
CalendarEventInformationWidget(
|
||||||
|
calendarEvent: calendarEvent,
|
||||||
|
onOpenComposerAction: controller.openNewComposerAction,
|
||||||
|
onOpenNewTabAction: controller.openNewTabAction,
|
||||||
|
),
|
||||||
if (calendarEvent.getTitleEventAction(context, listEmailAddressSender).isNotEmpty)
|
if (calendarEvent.getTitleEventAction(context, listEmailAddressSender).isNotEmpty)
|
||||||
CalendarEventActionBannerWidget(
|
CalendarEventActionBannerWidget(
|
||||||
calendarEvent: calendarEvent,
|
calendarEvent: calendarEvent,
|
||||||
listEmailAddressSender: listEmailAddressSender
|
listEmailAddressSender: listEmailAddressSender
|
||||||
),
|
),
|
||||||
CalendarEventDetailWidget(calendarEvent: calendarEvent),
|
CalendarEventDetailWidget(
|
||||||
|
calendarEvent: calendarEvent,
|
||||||
|
onOpenComposerAction: controller.openNewComposerAction,
|
||||||
|
onOpenNewTabAction: controller.openNewTabAction,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+10
-2
@@ -13,10 +13,14 @@ import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event
|
|||||||
class CalendarEventDetailWidget extends StatelessWidget {
|
class CalendarEventDetailWidget extends StatelessWidget {
|
||||||
|
|
||||||
final CalendarEvent calendarEvent;
|
final CalendarEvent calendarEvent;
|
||||||
|
final OnOpenNewTabAction? onOpenNewTabAction;
|
||||||
|
final OnOpenComposerAction? onOpenComposerAction;
|
||||||
|
|
||||||
const CalendarEventDetailWidget({
|
const CalendarEventDetailWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.calendarEvent
|
required this.calendarEvent,
|
||||||
|
this.onOpenNewTabAction,
|
||||||
|
this.onOpenComposerAction,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -61,7 +65,11 @@ class CalendarEventDetailWidget extends StatelessWidget {
|
|||||||
if (calendarEvent.location?.isNotEmpty == true)
|
if (calendarEvent.location?.isNotEmpty == true)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
|
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)
|
if (calendarEvent.participants?.isNotEmpty == true && calendarEvent.organizer != null)
|
||||||
Padding(
|
Padding(
|
||||||
|
|||||||
+16
-3
@@ -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/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/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/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_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_time_information_widget.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_title_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 {
|
class CalendarEventInformationWidget extends StatelessWidget {
|
||||||
|
|
||||||
final CalendarEvent calendarEvent;
|
final CalendarEvent calendarEvent;
|
||||||
|
final OnOpenNewTabAction? onOpenNewTabAction;
|
||||||
|
final OnOpenComposerAction? onOpenComposerAction;
|
||||||
|
|
||||||
const CalendarEventInformationWidget({
|
const CalendarEventInformationWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.calendarEvent
|
required this.calendarEvent,
|
||||||
|
this.onOpenNewTabAction,
|
||||||
|
this.onOpenComposerAction,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -93,7 +98,11 @@ class CalendarEventInformationWidget extends StatelessWidget {
|
|||||||
if (calendarEvent.location?.isNotEmpty == true)
|
if (calendarEvent.location?.isNotEmpty == true)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
|
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)
|
if (calendarEvent.participants?.isNotEmpty == true && calendarEvent.organizer != null)
|
||||||
Padding(
|
Padding(
|
||||||
@@ -158,7 +167,11 @@ class CalendarEventInformationWidget extends StatelessWidget {
|
|||||||
if (calendarEvent.location?.isNotEmpty == true)
|
if (calendarEvent.location?.isNotEmpty == true)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
|
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)
|
if (calendarEvent.participants?.isNotEmpty == true && calendarEvent.organizer != null)
|
||||||
Padding(
|
Padding(
|
||||||
|
|||||||
+29
-3
@@ -1,15 +1,24 @@
|
|||||||
|
|
||||||
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:flutter/material.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/features/email/presentation/styles/event_location_detail_widget_styles.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.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 {
|
class EventLocationDetailWidget extends StatelessWidget {
|
||||||
|
|
||||||
final String locationEvent;
|
final String locationEvent;
|
||||||
|
final OnOpenNewTabAction? onOpenNewTabAction;
|
||||||
|
final OnOpenComposerAction? onOpenComposerAction;
|
||||||
|
|
||||||
const EventLocationDetailWidget({
|
const EventLocationDetailWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.locationEvent
|
required this.locationEvent,
|
||||||
|
this.onOpenNewTabAction,
|
||||||
|
this.onOpenComposerAction,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -28,13 +37,30 @@ class EventLocationDetailWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(child: Text(
|
Expanded(child: Linkify(
|
||||||
locationEvent,
|
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(
|
style: const TextStyle(
|
||||||
fontSize: EventLocationDetailWidgetStyles.textSize,
|
fontSize: EventLocationDetailWidgetStyles.textSize,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: EventLocationDetailWidgetStyles.valueColor
|
color: EventLocationDetailWidgetStyles.valueColor
|
||||||
),
|
),
|
||||||
|
options: const LinkifyOptions(
|
||||||
|
removeWww: true,
|
||||||
|
looseUrl: true,
|
||||||
|
defaultToHttps: true
|
||||||
|
),
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
+27
-10
@@ -1,23 +1,26 @@
|
|||||||
|
|
||||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:core/presentation/utils/style_utils.dart';
|
|
||||||
import 'package:flutter/material.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/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';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
class EventLocationInformationWidget extends StatelessWidget {
|
class EventLocationInformationWidget extends StatelessWidget {
|
||||||
|
|
||||||
final String locationEvent;
|
final String locationEvent;
|
||||||
|
final OnOpenNewTabAction? onOpenNewTabAction;
|
||||||
|
final OnOpenComposerAction? onOpenComposerAction;
|
||||||
|
|
||||||
const EventLocationInformationWidget({
|
const EventLocationInformationWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.locationEvent
|
required this.locationEvent,
|
||||||
|
this.onOpenNewTabAction,
|
||||||
|
this.onOpenComposerAction,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final responsiveUtils = Get.find<ResponsiveUtils>();
|
|
||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -32,16 +35,30 @@ class EventLocationInformationWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(child: Text(
|
Expanded(child: Linkify(
|
||||||
locationEvent,
|
onOpen: (element) {
|
||||||
overflow: responsiveUtils.isPortraitMobile(context) ? null : CommonTextStyle.defaultTextOverFlow,
|
log('EventLocationInformationWidget::build:element: $element');
|
||||||
softWrap: responsiveUtils.isPortraitMobile(context) ? null : CommonTextStyle.defaultSoftWrap,
|
if (element is UrlElement) {
|
||||||
maxLines: responsiveUtils.isPortraitMobile(context) ? null : 1,
|
onOpenNewTabAction?.call(element.url);
|
||||||
|
} else if (element is EmailElement) {
|
||||||
|
onOpenComposerAction?.call(element.emailAddress);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
text: locationEvent,
|
||||||
|
linkifiers: const [
|
||||||
|
EmailLinkifier(),
|
||||||
|
UrlLinkifier()
|
||||||
|
],
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: EventLocationInformationWidgetStyles.textSize,
|
fontSize: EventLocationInformationWidgetStyles.textSize,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: EventLocationInformationWidgetStyles.valueColor
|
color: EventLocationInformationWidgetStyles.valueColor
|
||||||
),
|
),
|
||||||
|
options: const LinkifyOptions(
|
||||||
|
removeWww: true,
|
||||||
|
looseUrl: true,
|
||||||
|
defaultToHttps: true
|
||||||
|
),
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -711,6 +711,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.0"
|
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:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -205,6 +205,8 @@ dependencies:
|
|||||||
|
|
||||||
date_format: 2.0.7
|
date_format: 2.0.7
|
||||||
|
|
||||||
|
flutter_linkify: 6.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|||||||
Reference in New Issue
Block a user