TF-1886 Support RTL mode for HTML display
(cherry picked from commit 9ac393489e746b49073b1a2d98063481f4c894c6)
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
const nameClassToolTip = 'tmail-tooltip';
|
const nameClassToolTip = 'tmail-tooltip';
|
||||||
|
|
||||||
const tooltipLinkCss = '''
|
const tooltipLinkCss = '''
|
||||||
@@ -27,6 +29,7 @@ String generateHtml(String content, {
|
|||||||
String? styleCSS,
|
String? styleCSS,
|
||||||
String? javaScripts,
|
String? javaScripts,
|
||||||
bool hideScrollBar = true,
|
bool hideScrollBar = true,
|
||||||
|
TextDirection? direction
|
||||||
}) {
|
}) {
|
||||||
return '''
|
return '''
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@@ -53,7 +56,7 @@ String generateHtml(String content, {
|
|||||||
</style>
|
</style>
|
||||||
${javaScripts ?? ''}
|
${javaScripts ?? ''}
|
||||||
</head>
|
</head>
|
||||||
<body style = "overflow-x: hidden">
|
<body ${direction == TextDirection.rtl ? 'dir="rtl"' : ''} style = "overflow-x: hidden">
|
||||||
<div class="tmail-content">$content</div>
|
<div class="tmail-content">$content</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class HtmlContentViewerOnWeb extends StatefulWidget {
|
|||||||
final double widthContent;
|
final double widthContent;
|
||||||
final double heightContent;
|
final double heightContent;
|
||||||
final HtmlViewerControllerForWeb controller;
|
final HtmlViewerControllerForWeb controller;
|
||||||
|
final TextDirection? direction;
|
||||||
|
|
||||||
/// Handler for mailto: links
|
/// Handler for mailto: links
|
||||||
final Function(Uri?)? mailtoDelegate;
|
final Function(Uri?)? mailtoDelegate;
|
||||||
@@ -31,6 +32,7 @@ class HtmlContentViewerOnWeb extends StatefulWidget {
|
|||||||
required this.controller,
|
required this.controller,
|
||||||
this.allowResizeToDocumentSize = true,
|
this.allowResizeToDocumentSize = true,
|
||||||
this.mailtoDelegate,
|
this.mailtoDelegate,
|
||||||
|
this.direction,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -65,7 +67,9 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
|
|||||||
@override
|
@override
|
||||||
void didUpdateWidget(covariant HtmlContentViewerOnWeb oldWidget) {
|
void didUpdateWidget(covariant HtmlContentViewerOnWeb oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (widget.contentHtml != oldWidget.contentHtml) {
|
log('_HtmlContentViewerOnWebState::didUpdateWidget():Old-Direction: ${oldWidget.direction} | Current-Direction: ${widget.direction}');
|
||||||
|
if (widget.contentHtml != oldWidget.contentHtml ||
|
||||||
|
widget.direction != oldWidget.direction) {
|
||||||
createdViewId = _getRandString(10);
|
createdViewId = _getRandString(10);
|
||||||
widget.controller.viewId = createdViewId;
|
widget.controller.viewId = createdViewId;
|
||||||
_setUpWeb();
|
_setUpWeb();
|
||||||
@@ -167,7 +171,8 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
|
|||||||
minHeight: minHeight,
|
minHeight: minHeight,
|
||||||
minWidth: minWidth,
|
minWidth: minWidth,
|
||||||
styleCSS: tooltipLinkCss,
|
styleCSS: tooltipLinkCss,
|
||||||
javaScripts: webViewActionScripts + scriptsDisableZoom);
|
javaScripts: webViewActionScripts + scriptsDisableZoom,
|
||||||
|
direction: widget.direction);
|
||||||
|
|
||||||
return htmlTemplate;
|
return htmlTemplate;
|
||||||
}
|
}
|
||||||
@@ -276,21 +281,18 @@ class _HtmlContentViewerOnWebState extends State<HtmlContentViewerOnWeb> {
|
|||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Directionality(
|
return FutureBuilder<bool>(
|
||||||
textDirection: TextDirection.ltr,
|
future: webInit,
|
||||||
child: FutureBuilder<bool>(
|
builder: (context, snapshot) {
|
||||||
future: webInit,
|
if (snapshot.hasData) {
|
||||||
builder: (context, snapshot) {
|
return HtmlElementView(
|
||||||
if (snapshot.hasData) {
|
key: ValueKey(htmlData),
|
||||||
return HtmlElementView(
|
viewType: createdViewId,
|
||||||
key: ValueKey(htmlData),
|
);
|
||||||
viewType: createdViewId,
|
} else {
|
||||||
);
|
return Container();
|
||||||
} else {
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,7 @@ class HtmlContentViewer extends StatefulWidget {
|
|||||||
final double heightContent;
|
final double heightContent;
|
||||||
final OnScrollHorizontalEnd? onScrollHorizontalEnd;
|
final OnScrollHorizontalEnd? onScrollHorizontalEnd;
|
||||||
final OnWebViewLoaded? onWebViewLoaded;
|
final OnWebViewLoaded? onWebViewLoaded;
|
||||||
|
final TextDirection? direction;
|
||||||
|
|
||||||
/// Register this callback if you want a reference to the [InAppWebViewController].
|
/// Register this callback if you want a reference to the [InAppWebViewController].
|
||||||
final void Function(InAppWebViewController controller)? onCreated;
|
final void Function(InAppWebViewController controller)? onCreated;
|
||||||
@@ -43,6 +44,7 @@ class HtmlContentViewer extends StatefulWidget {
|
|||||||
this.onScrollHorizontalEnd,
|
this.onScrollHorizontalEnd,
|
||||||
this.urlLauncherDelegate,
|
this.urlLauncherDelegate,
|
||||||
this.mailtoDelegate,
|
this.mailtoDelegate,
|
||||||
|
this.direction,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -63,14 +65,19 @@ class _HtmlContentViewState extends State<HtmlContentViewer> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
actualHeight = widget.heightContent;
|
actualHeight = widget.heightContent;
|
||||||
_htmlData = generateHtml(widget.contentHtml);
|
_htmlData = generateHtml(widget.contentHtml, direction: widget.direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didUpdateWidget(covariant HtmlContentViewer oldWidget) {
|
void didUpdateWidget(covariant HtmlContentViewer oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (widget.contentHtml != oldWidget.contentHtml) {
|
log('_HtmlContentViewState::didUpdateWidget():Old-Direction: ${oldWidget.direction} | Current-Direction: ${widget.direction}');
|
||||||
_htmlData = generateHtml(widget.contentHtml);
|
if (widget.contentHtml != oldWidget.contentHtml ||
|
||||||
|
widget.direction != oldWidget.direction) {
|
||||||
|
_htmlData = generateHtml(
|
||||||
|
widget.contentHtml,
|
||||||
|
direction: widget.direction
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -447,11 +447,13 @@ class EmailView extends GetWidget<SingleEmailController> {
|
|||||||
|
|
||||||
if (BuildUtils.isWeb) {
|
if (BuildUtils.isWeb) {
|
||||||
return HtmlContentViewerOnWeb(
|
return HtmlContentViewerOnWeb(
|
||||||
widthContent: constraints.maxWidth,
|
widthContent: constraints.maxWidth,
|
||||||
heightContent: responsiveUtils.getSizeScreenHeight(context),
|
heightContent: responsiveUtils.getSizeScreenHeight(context),
|
||||||
contentHtml: allEmailContents ?? "",
|
contentHtml: allEmailContents ?? "",
|
||||||
controller: HtmlViewerControllerForWeb(),
|
controller: HtmlViewerControllerForWeb(),
|
||||||
mailtoDelegate: (uri) => controller.openMailToLink(uri));
|
mailtoDelegate: (uri) => controller.openMailToLink(uri),
|
||||||
|
direction: AppUtils.getCurrentDirection(context),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return HtmlContentViewer(
|
return HtmlContentViewer(
|
||||||
heightContent: responsiveUtils.getSizeScreenHeight(context),
|
heightContent: responsiveUtils.getSizeScreenHeight(context),
|
||||||
@@ -462,6 +464,7 @@ class EmailView extends GetWidget<SingleEmailController> {
|
|||||||
log('EmailView::_buildEmailContent(): isScrollPageViewActivated: $isScrollPageViewActivated');
|
log('EmailView::_buildEmailContent(): isScrollPageViewActivated: $isScrollPageViewActivated');
|
||||||
controller.emailSupervisorController.updateScrollPhysicPageView(isScrollPageViewActivated: isScrollPageViewActivated);
|
controller.emailSupervisorController.updateScrollPhysicPageView(isScrollPageViewActivated: isScrollPageViewActivated);
|
||||||
},
|
},
|
||||||
|
direction: AppUtils.getCurrentDirection(context),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+7
-4
@@ -3,6 +3,7 @@ import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.d
|
|||||||
import 'package:core/presentation/views/html_viewer/html_viewer_controller_for_web.dart';
|
import 'package:core/presentation/views/html_viewer/html_viewer_controller_for_web.dart';
|
||||||
import 'package:core/utils/build_utils.dart';
|
import 'package:core/utils/build_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
||||||
|
|
||||||
class SignatureBuilder extends StatelessWidget {
|
class SignatureBuilder extends StatelessWidget {
|
||||||
|
|
||||||
@@ -27,13 +28,13 @@ class SignatureBuilder extends StatelessWidget {
|
|||||||
width: signatureWidth,
|
width: signatureWidth,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0),
|
||||||
child: _buildSignature(signatureWidth, signatureHeight),
|
child: _buildSignature(context, signatureWidth, signatureHeight),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSignature(double width, double height) {
|
Widget _buildSignature(BuildContext context, double width, double height) {
|
||||||
if (signatureSelected.isNotEmpty) {
|
if (signatureSelected.isNotEmpty) {
|
||||||
if (BuildUtils.isWeb) {
|
if (BuildUtils.isWeb) {
|
||||||
return HtmlContentViewerOnWeb(
|
return HtmlContentViewerOnWeb(
|
||||||
@@ -41,12 +42,14 @@ class SignatureBuilder extends StatelessWidget {
|
|||||||
widthContent: width,
|
widthContent: width,
|
||||||
heightContent: height,
|
heightContent: height,
|
||||||
controller: HtmlViewerControllerForWeb(),
|
controller: HtmlViewerControllerForWeb(),
|
||||||
allowResizeToDocumentSize: false
|
allowResizeToDocumentSize: false,
|
||||||
|
direction: AppUtils.getCurrentDirection(context),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return HtmlContentViewer(
|
return HtmlContentViewer(
|
||||||
contentHtml: signatureSelected,
|
contentHtml: signatureSelected,
|
||||||
heightContent: height
|
heightContent: height,
|
||||||
|
direction: AppUtils.getCurrentDirection(context),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ class AppUtils {
|
|||||||
return intl.Bidi.isRtlLanguage(Localizations.localeOf(context).languageCode);
|
return intl.Bidi.isRtlLanguage(Localizations.localeOf(context).languageCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TextDirection getCurrentDirection(BuildContext context) =>
|
||||||
|
isDirectionRTL(context) ? TextDirection.rtl : TextDirection.ltr;
|
||||||
|
|
||||||
static bool isEmailLocalhost(String email) {
|
static bool isEmailLocalhost(String email) {
|
||||||
return RegExp(r'^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@localhost$').hasMatch(email);
|
return RegExp(r'^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@localhost$').hasMatch(email);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user