diff --git a/core/lib/presentation/views/html_viewer/ios_html_content_viewer_widget.dart b/core/lib/presentation/views/html_viewer/ios_html_content_viewer_widget.dart new file mode 100644 index 000000000..2880ab5cf --- /dev/null +++ b/core/lib/presentation/views/html_viewer/ios_html_content_viewer_widget.dart @@ -0,0 +1,102 @@ +import 'dart:async'; + +import 'package:core/data/constants/constant.dart'; +import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart'; +import 'package:core/utils/html/html_interaction.dart'; +import 'package:core/utils/html/html_utils.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; +import 'package:url_launcher/url_launcher.dart' as launcher; +import 'package:url_launcher/url_launcher_string.dart'; + +class IosHtmlContentViewerWidget extends StatefulWidget { + + final String contentHtml; + final TextDirection? direction; + final bool useDefaultFont; + final OnMailtoDelegateAction? onMailtoDelegateAction; + final OnPreviewEMLDelegateAction? onPreviewEMLDelegateAction; + final OnDownloadAttachmentDelegateAction? onDownloadAttachmentDelegateAction; + + const IosHtmlContentViewerWidget({ + Key? key, + required this.contentHtml, + this.direction, + this.useDefaultFont = false, + this.onMailtoDelegateAction, + this.onPreviewEMLDelegateAction, + this.onDownloadAttachmentDelegateAction, + }) : super(key: key); + + @override + State createState() => _IosHtmlContentViewerWidgetState(); +} + +class _IosHtmlContentViewerWidgetState extends State { + + @override + Widget build(BuildContext context) { + return InAppWebView( + initialSettings: InAppWebViewSettings(transparentBackground: true), + onWebViewCreated: _onWebViewCreated, + shouldOverrideUrlLoading: _shouldOverrideUrlLoading, + gestureRecognizers: { + Factory(() => LongPressGestureRecognizer()), + }, + ); + } + + Future _onWebViewCreated(InAppWebViewController controller) async { + await controller.loadData(data: HtmlUtils.generateHtmlDocument( + content: widget.contentHtml, + direction: widget.direction, + javaScripts: HtmlInteraction.scriptsHandleLazyLoadingBackgroundImage, + useDefaultFont: widget.useDefaultFont, + )); + } + + Future _shouldOverrideUrlLoading( + InAppWebViewController controller, + NavigationAction navigationAction + ) async { + final url = navigationAction.request.url?.toString(); + + if (url == null) { + return NavigationActionPolicy.CANCEL; + } + + if (navigationAction.isForMainFrame && url == 'about:blank') { + return NavigationActionPolicy.ALLOW; + } + + final requestUri = Uri.parse(url); + if (widget.onMailtoDelegateAction != null && + requestUri.isScheme(Constant.mailtoScheme)) { + await widget.onMailtoDelegateAction?.call(requestUri); + return NavigationActionPolicy.CANCEL; + } + + if (widget.onPreviewEMLDelegateAction != null && + requestUri.isScheme(Constant.emlPreviewerScheme)) { + await widget.onPreviewEMLDelegateAction?.call(requestUri); + return NavigationActionPolicy.CANCEL; + } + + if (widget.onDownloadAttachmentDelegateAction != null && + requestUri.isScheme(Constant.attachmentScheme)) { + await widget.onDownloadAttachmentDelegateAction?.call(requestUri); + return NavigationActionPolicy.CANCEL; + } + + if (await launcher.canLaunchUrl(Uri.parse(url))) { + await launcher.launchUrl( + Uri.parse(url), + mode: LaunchMode.externalApplication + ); + } + + return NavigationActionPolicy.CANCEL; + } +} \ No newline at end of file diff --git a/lib/features/email/presentation/controller/single_email_controller.dart b/lib/features/email/presentation/controller/single_email_controller.dart index c879ae227..185cac018 100644 --- a/lib/features/email/presentation/controller/single_email_controller.dart +++ b/lib/features/email/presentation/controller/single_email_controller.dart @@ -2428,9 +2428,17 @@ class SingleEmailController extends BaseController with AppLoaderMixin { return; } - showModalSheetToPreviewEMLAttachment( - currentContext!, - success.emlPreviewer); + if (PlatformInfo.isAndroid) { + showModalSheetToPreviewEMLAttachment( + currentContext!, + success.emlPreviewer, + ); + } if (PlatformInfo.isIOS) { + showDialogToPreviewEMLAttachment( + currentContext!, + success.emlPreviewer, + ); + } } } @@ -2454,6 +2462,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin { initialChildSize: 1.0, builder: (context, ___) => EmailPreviewerDialogView( emlPreviewer: emlPreviewer, + imagePaths: imagePaths, onMailtoDelegateAction: openMailToLink, onPreviewEMLDelegateAction: (uri) => _openEMLPreviewer(context, uri), onDownloadAttachmentDelegateAction: (uri) => @@ -2464,6 +2473,20 @@ class SingleEmailController extends BaseController with AppLoaderMixin { ); } + void showDialogToPreviewEMLAttachment(BuildContext context, EMLPreviewer emlPreviewer) { + Get.dialog( + EmailPreviewerDialogView( + emlPreviewer: emlPreviewer, + imagePaths: imagePaths, + onMailtoDelegateAction: openMailToLink, + onPreviewEMLDelegateAction: (uri) => _openEMLPreviewer(context, uri), + onDownloadAttachmentDelegateAction: (uri) => + _downloadAttachmentInEMLPreview(context, uri), + ), + barrierColor: AppColor.colorDefaultCupertinoActionSheet, + ); + } + Future _openEMLPreviewer(BuildContext context, Uri? uri) async { log('SingleEmailController::_openEMLPreviewer:uri = $uri'); if (uri == null) return; diff --git a/lib/features/email_previewer/email_previewer_dialog_view.dart b/lib/features/email_previewer/email_previewer_dialog_view.dart index 483f59c4c..181c77195 100644 --- a/lib/features/email_previewer/email_previewer_dialog_view.dart +++ b/lib/features/email_previewer/email_previewer_dialog_view.dart @@ -1,13 +1,20 @@ +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart'; +import 'package:core/presentation/views/html_viewer/ios_html_content_viewer_widget.dart'; +import 'package:core/utils/platform_info.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:tmail_ui_user/features/email/presentation/model/eml_previewer.dart'; +import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/utils/app_utils.dart'; class EmailPreviewerDialogView extends StatelessWidget { final EMLPreviewer emlPreviewer; + final ImagePaths imagePaths; final OnMailtoDelegateAction onMailtoDelegateAction; final OnPreviewEMLDelegateAction onPreviewEMLDelegateAction; final OnDownloadAttachmentDelegateAction onDownloadAttachmentDelegateAction; @@ -15,6 +22,7 @@ class EmailPreviewerDialogView extends StatelessWidget { const EmailPreviewerDialogView({ super.key, required this.emlPreviewer, + required this.imagePaths, required this.onMailtoDelegateAction, required this.onPreviewEMLDelegateAction, required this.onDownloadAttachmentDelegateAction, @@ -22,18 +30,73 @@ class EmailPreviewerDialogView extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - body: SingleChildScrollView( - child: HtmlContentViewer( - contentHtml: emlPreviewer.content, - initialWidth: context.width, - direction: AppUtils.getCurrentDirection(context), - onMailtoDelegateAction: onMailtoDelegateAction, - onPreviewEMLDelegateAction: onPreviewEMLDelegateAction, - onDownloadAttachmentDelegateAction: onDownloadAttachmentDelegateAction, + if (PlatformInfo.isIOS) { + return Dialog( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topRight: Radius.circular(16), + topLeft: Radius.circular(16), + ), ), - ), - ); + insetPadding: EdgeInsets.zero, + alignment: Alignment.center, + backgroundColor: Colors.white, + child: Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + topRight: Radius.circular(16), + topLeft: Radius.circular(16), + ), + ), + width: double.infinity, + height: double.infinity, + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + SizedBox( + height: 52, + child: Row( + children: [ + const Spacer(), + TMailButtonWidget.fromIcon( + icon: imagePaths.icComposerClose, + backgroundColor: Colors.transparent, + margin: const EdgeInsetsDirectional.only(end: 12), + onTapActionCallback: popBack, + ) + ], + ), + ), + const Divider(color: AppColor.colorDivider, height: 1), + Expanded( + child: IosHtmlContentViewerWidget( + contentHtml: emlPreviewer.content, + useDefaultFont: true, + direction: AppUtils.getCurrentDirection(context), + onMailtoDelegateAction: onMailtoDelegateAction, + onPreviewEMLDelegateAction: onPreviewEMLDelegateAction, + onDownloadAttachmentDelegateAction: onDownloadAttachmentDelegateAction, + ), + ), + ], + ), + ), + ); + } else { + return Scaffold( + backgroundColor: Colors.white, + body: SingleChildScrollView( + child: HtmlContentViewer( + contentHtml: emlPreviewer.content, + initialWidth: context.width, + useDefaultFont: true, + direction: AppUtils.getCurrentDirection(context), + onMailtoDelegateAction: onMailtoDelegateAction, + onPreviewEMLDelegateAction: onPreviewEMLDelegateAction, + onDownloadAttachmentDelegateAction: onDownloadAttachmentDelegateAction, + ), + ), + ); + } } } \ No newline at end of file