TF-3416 Handle open EML attachment in EML previewer
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class PreviewAttachment with EquatableMixin {
|
||||
final String iconBase64Data;
|
||||
final String name;
|
||||
final String size;
|
||||
final String? link;
|
||||
|
||||
PreviewAttachment({
|
||||
required this.iconBase64Data,
|
||||
required this.name,
|
||||
required this.size,
|
||||
this.link,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
iconBase64Data,
|
||||
name,
|
||||
size,
|
||||
link,
|
||||
];
|
||||
}
|
||||
@@ -24,3 +24,5 @@ class SaveToWebSessionFailException with EquatableMixin implements Exception {
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class CannotOpenNewWindowException implements Exception {}
|
||||
|
||||
@@ -11,6 +11,8 @@ import 'package:core/utils/html/html_utils.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
|
||||
typedef OnClickHyperLinkAction = Function(Uri?);
|
||||
|
||||
class HtmlContentViewerOnWeb extends StatefulWidget {
|
||||
|
||||
final String contentHtml;
|
||||
@@ -21,6 +23,8 @@ class HtmlContentViewerOnWeb extends StatefulWidget {
|
||||
/// Handler for mailto: links
|
||||
final Function(Uri?)? mailtoDelegate;
|
||||
|
||||
final OnClickHyperLinkAction? onClickHyperLinkAction;
|
||||
|
||||
// if widthContent is bigger than width of htmlContent, set this to true let widget able to resize to width of htmlContent
|
||||
final bool allowResizeToDocumentSize;
|
||||
|
||||
@@ -32,6 +36,7 @@ class HtmlContentViewerOnWeb extends StatefulWidget {
|
||||
this.allowResizeToDocumentSize = true,
|
||||
this.mailtoDelegate,
|
||||
this.direction,
|
||||
this.onClickHyperLinkAction,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -55,6 +60,7 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
|
||||
late final StreamSubscription<html.MessageEvent> sizeListener;
|
||||
bool _iframeLoaded = false;
|
||||
static const String iframeOnLoadMessage = 'iframeHasBeenLoaded';
|
||||
static const String onClickHyperLinkName = 'onClickHyperLink';
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -113,6 +119,13 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data['type'] != null && data['type'].contains('toDart: $onClickHyperLinkName')) {
|
||||
final link = data['url'] as String?;
|
||||
if (link != null && mounted) {
|
||||
widget.onClickHyperLinkAction?.call(Uri.parse(link));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,21 +186,50 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
|
||||
}
|
||||
}
|
||||
|
||||
function handleOnClickEmailLink(e) {
|
||||
var href = this.href;
|
||||
window.parent.postMessage(JSON.stringify({"view": "$_createdViewId", "type": "toDart: OpenLink", "url": "" + href}), "*");
|
||||
e.preventDefault();
|
||||
}
|
||||
${widget.mailtoDelegate != null
|
||||
? '''
|
||||
function handleOnClickEmailLink(e) {
|
||||
var href = this.href;
|
||||
window.parent.postMessage(JSON.stringify({"view": "$_createdViewId", "type": "toDart: OpenLink", "url": "" + href}), "*");
|
||||
e.preventDefault();
|
||||
}
|
||||
'''
|
||||
: ''}
|
||||
|
||||
|
||||
|
||||
${widget.onClickHyperLinkAction != null
|
||||
? '''
|
||||
function onClickHyperLink(e) {
|
||||
var href = this.href;
|
||||
window.parent.postMessage(JSON.stringify({"view": "$_createdViewId", "type": "toDart: $onClickHyperLinkName", "url": "" + href}), "*");
|
||||
e.preventDefault();
|
||||
}
|
||||
'''
|
||||
: ''}
|
||||
|
||||
function handleOnLoad() {
|
||||
window.parent.postMessage(JSON.stringify({"view": "$_createdViewId", "message": "$iframeOnLoadMessage"}), "*");
|
||||
window.parent.postMessage(JSON.stringify({"view": "$_createdViewId", "type": "toIframe: getHeight"}), "*");
|
||||
window.parent.postMessage(JSON.stringify({"view": "$_createdViewId", "type": "toIframe: getWidth"}), "*");
|
||||
|
||||
var emailLinks = document.querySelectorAll('a[href^="mailto:"]');
|
||||
for(var i=0; i < emailLinks.length; i++){
|
||||
emailLinks[i].addEventListener('click', handleOnClickEmailLink);
|
||||
}
|
||||
${widget.onClickHyperLinkAction != null
|
||||
? '''
|
||||
var hyperLinks = document.querySelectorAll('a');
|
||||
for (var i=0; i < hyperLinks.length; i++){
|
||||
hyperLinks[i].addEventListener('click', onClickHyperLink);
|
||||
}
|
||||
'''
|
||||
: ''}
|
||||
|
||||
${widget.mailtoDelegate != null
|
||||
? '''
|
||||
var emailLinks = document.querySelectorAll('a[href^="mailto:"]');
|
||||
for (var i=0; i < emailLinks.length; i++){
|
||||
emailLinks[i].addEventListener('click', handleOnClickEmailLink);
|
||||
}
|
||||
'''
|
||||
: ''}
|
||||
}
|
||||
</script>
|
||||
''';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'js_interop_stub.dart' if (dart.library.html) 'dart:js_interop';
|
||||
import 'dart:typed_data';
|
||||
@@ -11,6 +12,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
|
||||
class HtmlUtils {
|
||||
static final random = Random();
|
||||
|
||||
static const lineHeight100Percent = (
|
||||
script: '''
|
||||
document.querySelectorAll("*")
|
||||
@@ -422,27 +425,62 @@ class HtmlUtils {
|
||||
fileSizeSpan.textContent = formatFileSize(bytesJs.length);''';
|
||||
}
|
||||
|
||||
static void openNewWindowByUrl(
|
||||
static bool openNewWindowByUrl(
|
||||
String url,
|
||||
{
|
||||
int width = 800,
|
||||
int height = 600,
|
||||
bool isFullScreen = false,
|
||||
bool isCenter = true,
|
||||
}
|
||||
) async {
|
||||
) {
|
||||
try {
|
||||
if (isFullScreen) {
|
||||
final screenWidth = html.window.screen?.width;
|
||||
final screenHeight = html.window.screen?.height;
|
||||
|
||||
final options = 'width=$screenWidth,height=$screenHeight';
|
||||
|
||||
html.window.open(url, '_blank', options);
|
||||
|
||||
html.Url.revokeObjectUrl(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
final screenWidth = html.window.screen?.width ?? width;
|
||||
final screenHeight = html.window.screen?.height ?? height;
|
||||
|
||||
final left = (screenWidth - width) ~/ 2;
|
||||
final top = (screenHeight - height) ~/ 2;
|
||||
int left, top;
|
||||
|
||||
if (isCenter) {
|
||||
left = (screenWidth - width) ~/ 2;
|
||||
top = (screenHeight - height) ~/ 2;
|
||||
} else {
|
||||
left = random.nextInt(screenWidth ~/ 2);
|
||||
top = random.nextInt(screenHeight ~/ 2);
|
||||
}
|
||||
|
||||
final options = 'width=$width,height=$height,top=$top,left=$left';
|
||||
|
||||
html.window.open(url, '_blank', options);
|
||||
|
||||
html.Url.revokeObjectUrl(url);
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
logError('AppUtils::openNewWindowByUrl:Exception = $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void setWindowBrowserTitle(String title) {
|
||||
try {
|
||||
final titleElements = html.window.document.getElementsByTagName('title');
|
||||
if (titleElements.isNotEmpty) {
|
||||
titleElements.first.text = title;
|
||||
}
|
||||
} catch (e) {
|
||||
logError('AppUtils::setWindowBrowserTitle:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import 'package:core/data/model/print_attachment.dart';
|
||||
import 'package:core/data/model/preview_attachment.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/html/html_template.dart';
|
||||
import 'package:core/utils/html/html_utils.dart';
|
||||
@@ -26,7 +26,7 @@ class PreviewEmlFileUtils {
|
||||
String? dateTime,
|
||||
String? attachmentIcon,
|
||||
String? emailContent,
|
||||
List<PrintAttachment>? listAttachment,
|
||||
List<PreviewAttachment>? listAttachment,
|
||||
}) {
|
||||
try {
|
||||
return Element.html('''
|
||||
@@ -83,23 +83,38 @@ class PreviewEmlFileUtils {
|
||||
}
|
||||
}
|
||||
|
||||
String _createAttachmentHtmlTag(PrintAttachment printAttachment) {
|
||||
String _createAttachmentHtmlTag(PreviewAttachment previewAttachment) {
|
||||
return '''
|
||||
<div class="attachment-item">
|
||||
<div class="icon">
|
||||
<img width="16" height="16" src="${HtmlUtils.generateSVGImageData(printAttachment.iconBase64Data)}" alt="attachment-icon"/>
|
||||
</div>
|
||||
<div class="file-details">
|
||||
<div class="file-name">${printAttachment.name}</div>
|
||||
<div class="file-size">${printAttachment.size}</div>
|
||||
</div>
|
||||
</div>
|
||||
${previewAttachment.link?.isNotEmpty == true
|
||||
? '''
|
||||
<a href="${previewAttachment.link}" class="attachment-item">
|
||||
<div class="icon">
|
||||
<img width="16" height="16" src="${HtmlUtils.generateSVGImageData(previewAttachment.iconBase64Data)}" alt="attachment-icon"/>
|
||||
</div>
|
||||
<div class="file-details">
|
||||
<div class="file-name">${previewAttachment.name}</div>
|
||||
<div class="file-size">${previewAttachment.size}</div>
|
||||
</div>
|
||||
</a>
|
||||
'''
|
||||
: '''
|
||||
<div class="attachment-item">
|
||||
<div class="icon">
|
||||
<img width="16" height="16" src="${HtmlUtils.generateSVGImageData(previewAttachment.iconBase64Data)}" alt="attachment-icon"/>
|
||||
</div>
|
||||
<div class="file-details">
|
||||
<div class="file-name">${previewAttachment.name}</div>
|
||||
<div class="file-size">${previewAttachment.size}</div>
|
||||
</div>
|
||||
</div>
|
||||
'''}
|
||||
|
||||
''';
|
||||
}
|
||||
|
||||
String _createAttachmentsElement({
|
||||
required String titleAttachment,
|
||||
required List<PrintAttachment> listAttachment
|
||||
required List<PreviewAttachment> listAttachment
|
||||
}) {
|
||||
try {
|
||||
return '''
|
||||
@@ -137,7 +152,7 @@ class PreviewEmlFileUtils {
|
||||
String? ccAddress,
|
||||
String? bccAddress,
|
||||
String? replyToAddress,
|
||||
List<PrintAttachment>? listAttachment,
|
||||
List<PreviewAttachment>? listAttachment,
|
||||
}) {
|
||||
Document document = parse(HtmlUtils.createTemplateHtmlDocument(title: '$subject - $userName'));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user