diff --git a/core/lib/presentation/views/html_viewer/html_content_viewer_widget.dart b/core/lib/presentation/views/html_viewer/html_content_viewer_widget.dart index 920b80b8e..16f8eb740 100644 --- a/core/lib/presentation/views/html_viewer/html_content_viewer_widget.dart +++ b/core/lib/presentation/views/html_viewer/html_content_viewer_widget.dart @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; +import 'package:url_launcher/url_launcher.dart' as launcher; class _HtmlGenerationArguments { final String message; @@ -35,12 +36,22 @@ class HtmlContentViewer extends StatefulWidget { /// Register this callback if you want a reference to the [InAppWebViewController]. final void Function(InAppWebViewController controller)? onWebViewCreated; + final void Function(InAppWebViewController controller, Uri? uri)? onWebViewLoadStart; + + final void Function(InAppWebViewController controller, Uri? uri)? onWebViewLoadStop; + + /// Handler for mailto: links + final Future Function(Uri mailto)? mailtoDelegate; + const HtmlContentViewer({ Key? key, required this.message, this.blockExternalImages = false, this.onError, this.onWebViewCreated, + this.onWebViewLoadStart, + this.onWebViewLoadStop, + this.mailtoDelegate, }) : super(key: key); @override @@ -144,6 +155,11 @@ class _HtmlContentViewState extends State { enableViewportScale: true, ) ), + onLoadStart: (controller, uri) { + if (widget.onWebViewLoadStart != null) { + widget.onWebViewLoadStart!(controller, uri); + } + }, onWebViewCreated: widget.onWebViewCreated, onLoadStop: (controller, uri) async { var scrollHeight = (await controller.evaluateJavascript(source: 'document.body.scrollHeight')); @@ -162,10 +178,34 @@ class _HtmlContentViewState extends State { _webViewContentHeight = double.tryParse('${scrollHeight + 10.0}'); }); } + + if (widget.onWebViewLoadStop != null) { + widget.onWebViewLoadStop!(controller, uri); + } }, + shouldOverrideUrlLoading: _shouldOverrideUrlLoading, gestureRecognizers: { Factory(() => LongPressGestureRecognizer()), }, ); } + + Future _shouldOverrideUrlLoading( + InAppWebViewController controller, + NavigationAction request + ) async { + final requestUri = request.request.url!; + final mailtoHandler = widget.mailtoDelegate; + if (mailtoHandler != null && requestUri.isScheme('mailto')) { + await mailtoHandler(requestUri); + return NavigationActionPolicy.CANCEL; + } + final url = requestUri.toString(); + if (await launcher.canLaunch(url)) { + await launcher.launch(url); + return NavigationActionPolicy.CANCEL; + } else { + return NavigationActionPolicy.ALLOW; + } + } } \ No newline at end of file diff --git a/core/pubspec.yaml b/core/pubspec.yaml index b01bc26d1..7d87eb532 100644 --- a/core/pubspec.yaml +++ b/core/pubspec.yaml @@ -1,6 +1,8 @@ name: core description: Core Module +# As we are not publishing this Installer in pub.dev, we can add publish_to: 'none' +publish_to: none # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 # followed by an optional build number separated by a +. @@ -59,11 +61,13 @@ dependencies: # getwidget getwidget: 2.0.4 - # enough_html_editor - enough_html_editor: + # flutter_inappwebview + flutter_inappwebview: git: - url: git://github.com/dab246/enough_html_editor.git - ref: fix_bug_enough_platform_widgets + url: https://github.com/robert-virkus/flutter_inappwebview.git + + # url_launcher + url_launcher: 6.0.6 dev_dependencies: flutter_test: diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart index 24834f763..7e0806c8a 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:core/core.dart'; +import 'package:dartz/dartz.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -8,6 +9,7 @@ import 'package:get/get.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/email/presentation/email_controller.dart'; import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart'; +import 'package:tmail_ui_user/features/email/presentation/model/web_view_state.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/app_bar_mail_widget_builder.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_file_tile_builder.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/bottom_bar_mail_widget_builder.dart'; @@ -119,7 +121,7 @@ class EmailView extends GetView { Widget _buildLoadingView() { return Obx(() => emailController.viewState.value.fold( (failure) => SizedBox.shrink(), - (success) => success is LoadingState + (success) => success is LoadingState || success is WebViewLoadingState ? Center(child: Padding( padding: EdgeInsets.only(top: 16, bottom: 16), child: SizedBox( @@ -148,8 +150,8 @@ class EmailView extends GetView { emailController.emailAddressExpandMode.value) .onOpenExpandAddressReceiverActionClick(() => emailController.toggleDisplayEmailAddressAction(expandMode: ExpandMode.EXPAND)) .build()), - _buildLoadingView(), _buildListAttachments(context), + _buildLoadingView(), _buildListMessageContent(), ], ) @@ -293,6 +295,13 @@ class EmailView extends GetView { color: AppColor.mailboxTextColor))) : HtmlContentViewer( message: messageContents.first.content, + onWebViewLoadStart: (webController, uri) { + emailController.dispatchState(Right(WebViewLoadingState())); + }, + onWebViewLoadStop: (webController, uri) { + emailController.clearState(); + }, + mailtoDelegate: (uri) async {}, ); } else { return SizedBox.shrink(); diff --git a/lib/features/email/presentation/model/web_view_state.dart b/lib/features/email/presentation/model/web_view_state.dart new file mode 100644 index 000000000..fede26ce7 --- /dev/null +++ b/lib/features/email/presentation/model/web_view_state.dart @@ -0,0 +1,9 @@ + +import 'package:core/core.dart'; + +class WebViewLoadingState extends UIState { + WebViewLoadingState(); + + @override + List get props => []; +} \ No newline at end of file diff --git a/model/pubspec.yaml b/model/pubspec.yaml index ef8a5b102..05e3392bf 100644 --- a/model/pubspec.yaml +++ b/model/pubspec.yaml @@ -1,6 +1,8 @@ name: model description: A model module contains entities +# As we are not publishing this Installer in pub.dev, we can add publish_to: 'none' +publish_to: none # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 # followed by an optional build number separated by a +.