TF-2116 Support show collapse/expand signature for email view

(cherry picked from commit 4f0bb84593af28473b34466570b9ecb75c720617)
This commit is contained in:
dab246
2023-09-12 16:32:07 +07:00
committed by Dat H. Pham
parent 3ac12ff258
commit 6626223926
8 changed files with 294 additions and 103 deletions
@@ -5,6 +5,7 @@ import 'dart:math' as math;
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/utils/html_transformer/html_template.dart';
import 'package:core/presentation/utils/html_transformer/html_utils.dart';
import 'package:core/presentation/utils/icon_utils.dart';
import 'package:core/presentation/views/html_viewer/html_viewer_controller_for_web.dart';
import 'package:core/utils/app_logger.dart';
import 'package:flutter/cupertino.dart';
@@ -54,6 +55,7 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
bool _isLoading = true;
double minHeight = 100;
double minWidth = 300;
final jsonEncoder = const JsonEncoder();
@override
void initState() {
@@ -101,6 +103,10 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
if (e && e.data && e.data.includes("toIframe:")) {
var data = JSON.parse(e.data);
if (data["view"].includes("$createdViewId")) {
if (data["type"].includes("showSignature")) {
${HtmlUtils.runScriptsCollapsedExpandedSignature}
}
if (data["type"].includes("getHeight")) {
var height = document.body.scrollHeight;
window.parent.postMessage(JSON.stringify({"view": "$createdViewId", "type": "toDart: htmlHeight", "height": height}), "*");
@@ -143,6 +149,23 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
return url.protocol === "mailto:";
}
function handleOnClickSignature() {
console.log("handleOnClickSignature");
const contentElement = document.querySelector('.tmail-content > .tmail-signature > .tmail-signature-content');
const buttonElement = document.querySelector('.tmail-content > .tmail-signature > .tmail-signature-button');
console.log("contentElement: " + contentElement);
console.log("buttonElement: " + buttonElement);
if (contentElement && buttonElement) {
if (contentElement.style.display === 'block') {
contentElement.style.display = 'none';
buttonElement.style.backgroundImage = `${IconUtils.chevronDownSVGIconUrlEncoded}`;
} else {
contentElement.style.display = 'block';
buttonElement.style.backgroundImage = `${IconUtils.chevronUpSVGIconUrlEncoded}`;
}
}
}
</script>
''';
@@ -188,15 +211,9 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
..style.width = '100%'
..style.height = '100%'
..onLoad.listen((event) async {
final dataGetHeight = <String, Object>{'type': 'toIframe: getHeight', 'view' : createdViewId};
final dataGetWidth = <String, Object>{'type': 'toIframe: getWidth', 'view' : createdViewId};
const jsonEncoder = JsonEncoder();
final jsonGetHeight = jsonEncoder.convert(dataGetHeight);
final jsonGetWidth = jsonEncoder.convert(dataGetWidth);
html.window.postMessage(jsonGetHeight, '*');
html.window.postMessage(jsonGetWidth, '*');
_sendMessageToWebViewForGetHeight();
_sendMessageToWebViewForGetWidth();
_sendMessageToWebViewForShowSignature();
html.window.onMessage.listen((event) {
var data = json.decode(event.data);
@@ -232,7 +249,6 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
if (data['type'] != null && data['type'].contains('toDart: OpenLink') && data['view'] == createdViewId) {
final link = data['url'];
if (link != null && mounted) {
log('_HtmlContentViewerOnWebState::_setUpWeb(): OpenLink: $link');
final urlString = link as String;
if (urlString.startsWith('mailto:')) {
widget.mailtoDelegate?.call(Uri.parse(urlString));
@@ -253,45 +269,76 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
@override
Widget build(BuildContext context) {
return Stack(
children: [
SizedBox(
height: actualHeight,
width: actualWidth,
child: _buildWebView(),
),
if (_isLoading) Align(alignment: Alignment.topCenter, child: _buildLoadingView())
],
);
return LayoutBuilder(builder: (context, constraint) {
minHeight = math.max(constraint.maxHeight, minHeight);
return Stack(
children: [
if (_htmlData?.isNotEmpty == false)
const SizedBox.shrink()
else
FutureBuilder<bool>(
future: webInit,
builder: (context, snapshot) {
if (snapshot.hasData) {
return SizedBox(
height: actualHeight,
width: actualWidth,
child: HtmlElementView(
key: ValueKey(_htmlData),
viewType: createdViewId,
),
);
} else {
return const SizedBox.shrink();
}
}
),
if (_isLoading)
const Align(
alignment: Alignment.topCenter,
child: Padding(
padding: EdgeInsets.all(16),
child: SizedBox(
width: 30,
height: 30,
child: CupertinoActivityIndicator(
color: AppColor.colorLoading
)
)
)
)
],
);
});
}
Widget _buildLoadingView() {
return const Padding(
padding: EdgeInsets.all(16),
child: SizedBox(
width: 30,
height: 30,
child: CupertinoActivityIndicator(color: AppColor.colorLoading)));
void _sendMessageToWebViewForGetHeight() {
final dataGetHeight = <String, Object>{
'type': 'toIframe: getHeight',
'view' : createdViewId
};
final jsonGetHeight = jsonEncoder.convert(dataGetHeight);
html.window.postMessage(jsonGetHeight, '*');
}
Widget _buildWebView() {
final htmlData = _htmlData;
if (htmlData == null || htmlData.isEmpty) {
return Container();
}
void _sendMessageToWebViewForGetWidth() {
final dataGetWidth = <String, Object>{
'type': 'toIframe: getWidth',
'view' : createdViewId
};
final jsonGetWidth = jsonEncoder.convert(dataGetWidth);
return FutureBuilder<bool>(
future: webInit,
builder: (context, snapshot) {
if (snapshot.hasData) {
return HtmlElementView(
key: ValueKey(htmlData),
viewType: createdViewId,
);
} else {
return Container();
}
}
);
html.window.postMessage(jsonGetWidth, '*');
}
void _sendMessageToWebViewForShowSignature() {
final dataShowSignature = <String, Object>{
'type': 'toIframe: showSignature',
'view' : createdViewId
};
final jsonShowSignature = jsonEncoder.convert(dataShowSignature);
html.window.postMessage(jsonShowSignature, '*');
}
}
@@ -68,7 +68,7 @@ class _HtmlContentViewState extends State<HtmlContentViewer> {
_htmlData = generateHtml(
widget.contentHtml,
direction: widget.direction,
javaScripts: HtmlUtils.scriptLazyLoadImage,
javaScripts: HtmlUtils.scriptLazyLoadImage + HtmlUtils.scriptCollapsedExpandedSignatureOnMobile,
);
}
@@ -81,7 +81,7 @@ class _HtmlContentViewState extends State<HtmlContentViewer> {
_htmlData = generateHtml(
widget.contentHtml,
direction: widget.direction,
javaScripts: HtmlUtils.scriptLazyLoadImage,
javaScripts: HtmlUtils.scriptLazyLoadImage + HtmlUtils.scriptCollapsedExpandedSignatureOnMobile,
);
}
}
@@ -91,61 +91,58 @@ class _HtmlContentViewState extends State<HtmlContentViewer> {
return LayoutBuilder(builder: (context, constraints) {
return Stack(
children: [
SizedBox(
height: actualHeight,
width: constraints.maxWidth,
child: _buildWebView()),
if (_htmlData?.isNotEmpty == false)
const SizedBox.shrink()
else
SizedBox(
height: actualHeight,
width: constraints.maxWidth,
child: InAppWebView(
key: ValueKey(_htmlData),
initialSettings: InAppWebViewSettings(
transparentBackground: true,
),
onWebViewCreated: (controller) async {
_webViewController = controller;
await controller.loadData(data: _htmlData ?? '');
widget.onCreated?.call(controller);
},
onLoadStop: _onLoadStop,
shouldOverrideUrlLoading: _shouldOverrideUrlLoading,
gestureRecognizers: {
Factory<LongPressGestureRecognizer>(() => LongPressGestureRecognizer()),
if (Platform.isIOS && horizontalGestureActivated)
Factory<HorizontalDragGestureRecognizer>(() => HorizontalDragGestureRecognizer()),
if (Platform.isAndroid)
Factory<ScaleGestureRecognizer>(() => ScaleGestureRecognizer()),
},
onScrollChanged: (controller, x, y) => controller.scrollTo(x: 0, y: 0)
),
),
if (_isLoading)
Align(
alignment: Alignment.center,
child: _buildLoadingView()
const Align(
alignment: Alignment.topCenter,
child: Padding(
padding: EdgeInsets.all(16),
child: SizedBox(
width: 30,
height: 30,
child: CupertinoActivityIndicator(
color: AppColor.colorLoading
)
)
)
)
],
);
});
}
Widget _buildLoadingView() {
return const Padding(
padding: EdgeInsets.all(16),
child: SizedBox(
width: 30,
height: 30,
child: CupertinoActivityIndicator(color: AppColor.colorLoading)));
}
Widget _buildWebView() {
final htmlData = _htmlData;
if (htmlData == null || htmlData.isEmpty) {
return Container();
}
return InAppWebView(
key: ValueKey(htmlData),
initialSettings: InAppWebViewSettings(
transparentBackground: true,
),
onWebViewCreated: (controller) async {
_webViewController = controller;
controller.loadData(data: htmlData);
widget.onCreated?.call(controller);
},
onLoadStop: _onLoadStop,
shouldOverrideUrlLoading: _shouldOverrideUrlLoading,
gestureRecognizers: {
Factory<LongPressGestureRecognizer>(() => LongPressGestureRecognizer()),
if (Platform.isIOS && horizontalGestureActivated)
Factory<HorizontalDragGestureRecognizer>(() => HorizontalDragGestureRecognizer()),
if (Platform.isAndroid)
Factory<ScaleGestureRecognizer>(() => ScaleGestureRecognizer()),
},
onScrollChanged: (controller, x, y) => controller.scrollTo(x: 0, y: 0)
);
}
void _onLoadStop(InAppWebViewController controller, WebUri? webUri) async {
await Future.wait([
_setActualHeightView(),
_setActualWidthView(),
_showSignature(),
]);
_hideLoadingProgress();
@@ -169,7 +166,6 @@ class _HtmlContentViewState extends State<HtmlContentViewer> {
Future<void> _setActualHeightView() async {
final scrollHeight = await _webViewController.evaluateJavascript(source: 'document.body.scrollHeight');
log('_HtmlContentViewState::_setActualHeightView(): scrollHeight: $scrollHeight');
if (scrollHeight != null && mounted) {
final scrollHeightWithBuffer = scrollHeight + 30.0;
if (scrollHeightWithBuffer > minHeight) {
@@ -192,12 +188,8 @@ class _HtmlContentViewState extends State<HtmlContentViewer> {
if (result.length == 2) {
final scrollWidth = result[0];
final offsetWidth = result[1];
log('_HtmlContentViewState::_setActualWidthView():scrollWidth: $scrollWidth');
log('_HtmlContentViewState::_setActualWidthView():offsetWidth: $offsetWidth');
if (scrollWidth != null && offsetWidth != null && mounted) {
final isScrollActivated = scrollWidth.round() == offsetWidth.round();
log('_HtmlContentViewState::_setActualWidthView():isScrollActivated: $isScrollActivated');
if (isScrollActivated) {
setState(() {
horizontalGestureActivated = false;
@@ -215,6 +207,12 @@ class _HtmlContentViewState extends State<HtmlContentViewer> {
}
}
Future<void> _showSignature() async {
await _webViewController.evaluateJavascript(
source: 'showSignature();'
);
}
void _hideLoadingProgress() {
if (mounted && _isLoading) {
setState(() {