TF-3601 Fix preview EML file with long content in iOS

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-03-31 03:45:05 +07:00
committed by Dat H. Pham
parent d01618c32e
commit 1c97c8a189
3 changed files with 203 additions and 15 deletions
@@ -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<StatefulWidget> createState() => _IosHtmlContentViewerWidgetState();
}
class _IosHtmlContentViewerWidgetState extends State<IosHtmlContentViewerWidget> {
@override
Widget build(BuildContext context) {
return InAppWebView(
initialSettings: InAppWebViewSettings(transparentBackground: true),
onWebViewCreated: _onWebViewCreated,
shouldOverrideUrlLoading: _shouldOverrideUrlLoading,
gestureRecognizers: {
Factory<LongPressGestureRecognizer>(() => LongPressGestureRecognizer()),
},
);
}
Future<void> _onWebViewCreated(InAppWebViewController controller) async {
await controller.loadData(data: HtmlUtils.generateHtmlDocument(
content: widget.contentHtml,
direction: widget.direction,
javaScripts: HtmlInteraction.scriptsHandleLazyLoadingBackgroundImage,
useDefaultFont: widget.useDefaultFont,
));
}
Future<NavigationActionPolicy?> _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;
}
}
@@ -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<void> _openEMLPreviewer(BuildContext context, Uri? uri) async {
log('SingleEmailController::_openEMLPreviewer:uri = $uri');
if (uri == null) return;
@@ -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,
),
),
);
}
}
}