Support vertical scrolling of all information between app bar and bottom bar in email view

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-07-09 15:26:24 +07:00
committed by Dat H. Pham
parent 3ce7c60cef
commit a4d7fec6e1
4 changed files with 71 additions and 76 deletions
@@ -48,7 +48,7 @@ class HtmlContentViewerOnWeb extends StatefulWidget {
Key? key, Key? key,
required this.contentHtml, required this.contentHtml,
required this.widthContent, required this.widthContent,
required this.heightContent, this.heightContent = 200,
this.allowResizeToDocumentSize = true, this.allowResizeToDocumentSize = true,
this.useDefaultFont = false, this.useDefaultFont = false,
this.mailtoDelegate, this.mailtoDelegate,
@@ -190,6 +190,8 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
final attendanceStatus = Rxn<AttendanceStatus>(); final attendanceStatus = Rxn<AttendanceStatus>();
final htmlContentViewKey = GlobalKey<HtmlContentViewState>(); final htmlContentViewKey = GlobalKey<HtmlContentViewState>();
final ScrollController emailScrollController = ScrollController();
Identity? _identitySelected; Identity? _identitySelected;
ButtonState? _printEmailButtonState; ButtonState? _printEmailButtonState;
final obxListeners = <Worker>[]; final obxListeners = <Worker>[];
@@ -263,6 +265,7 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
_threadDetailController = null; _threadDetailController = null;
_downloadProgressStateController.close(); _downloadProgressStateController.close();
_attachmentListScrollController.dispose(); _attachmentListScrollController.dispose();
emailScrollController.dispose();
super.onClose(); super.onClose();
} }
+67 -74
View File
@@ -1,5 +1,3 @@
import 'dart:math';
import 'package:core/presentation/constants/constants_ui.dart'; import 'package:core/presentation/constants/constants_ui.dart';
import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/views/html_viewer/html_content_viewer_on_web_widget.dart'; import 'package:core/presentation/views/html_viewer/html_content_viewer_on_web_widget.dart';
@@ -153,7 +151,7 @@ class EmailView extends GetWidget<SingleEmailController> {
context: context, context: context,
presentationEmail: currentEmail, presentationEmail: currentEmail,
calendarEvent: controller.calendarEvent, calendarEvent: controller.calendarEvent,
maxBodyHeight: constraints.maxHeight, bodyConstraints: constraints,
), ),
), ),
), ),
@@ -177,16 +175,36 @@ class EmailView extends GetWidget<SingleEmailController> {
presentationEmail: currentEmail, presentationEmail: currentEmail,
calendarEvent: calendarEvent, calendarEvent: calendarEvent,
emailAddressSender: currentEmail.listEmailAddressSender.getListAddress(), emailAddressSender: currentEmail.listEmailAddressSender.getListAddress(),
maxBodyHeight: constraints.maxHeight, bodyConstraints: constraints,
), ),
), ),
), ),
); );
} else { } else {
return _buildEmailMessage( return Stack(
context: context, children: [
presentationEmail: currentEmail, OptionalScroll(
maxBodyHeight: constraints.maxHeight, scrollEnabled: !isInsideThreadDetailView,
scrollPhysics : const ClampingScrollPhysics(),
child: _buildEmailMessage(
context: context,
presentationEmail: currentEmail,
bodyConstraints: constraints,
),
),
Obx(() {
if (controller.mailboxDashBoardController.isDisplayedOverlayViewOnIFrame) {
return PointerInterceptor(
child: SizedBox(
width: constraints.maxWidth,
height: constraints.maxHeight,
),
);
} else {
return const SizedBox.shrink();
}
}),
],
); );
} }
}); });
@@ -270,9 +288,9 @@ class EmailView extends GetWidget<SingleEmailController> {
Widget _buildEmailMessage({ Widget _buildEmailMessage({
required BuildContext context, required BuildContext context,
required PresentationEmail presentationEmail, required PresentationEmail presentationEmail,
required BoxConstraints bodyConstraints,
CalendarEvent? calendarEvent, CalendarEvent? calendarEvent,
List<String>? emailAddressSender, List<String>? emailAddressSender,
double? maxBodyHeight,
}) { }) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -292,7 +310,7 @@ class EmailView extends GetWidget<SingleEmailController> {
responsiveUtils: controller.responsiveUtils, responsiveUtils: controller.responsiveUtils,
sMimeStatus: controller.currentEmailLoaded.value?.sMimeStatus, sMimeStatus: controller.currentEmailLoaded.value?.sMimeStatus,
emailUnsubscribe: controller.emailUnsubscribe.value, emailUnsubscribe: controller.emailUnsubscribe.value,
maxBodyHeight: maxBodyHeight, maxBodyHeight: bodyConstraints.maxHeight,
openEmailAddressDetailAction: (_, emailAddress) => controller.openEmailAddressDialog(emailAddress), openEmailAddressDetailAction: (_, emailAddress) => controller.openEmailAddressDialog(emailAddress),
onEmailActionClick: (presentationEmail, actionType) => controller.handleEmailAction(context, presentationEmail, actionType), onEmailActionClick: (presentationEmail, actionType) => controller.handleEmailAction(context, presentationEmail, actionType),
isInsideThreadDetailView: isInsideThreadDetailView, isInsideThreadDetailView: isInsideThreadDetailView,
@@ -394,39 +412,18 @@ class EmailView extends GetWidget<SingleEmailController> {
final allEmailContents = controller.emailContents.value ?? ''; final allEmailContents = controller.emailContents.value ?? '';
if (PlatformInfo.isWeb) { if (PlatformInfo.isWeb) {
return OptionalExpanded( return Padding(
expandedEnabled: !isInsideThreadDetailView, padding: EmailViewStyles.emailContentPadding,
child: Padding( child: HtmlContentViewerOnWeb(
padding: EmailViewStyles.emailContentPadding, key: ValueKey(tag),
child: LayoutBuilder(builder: (context, constraints) { widthContent: bodyConstraints.maxWidth,
return Obx(() { contentHtml: allEmailContents,
return Stack( mailtoDelegate: controller.openMailToLink,
children: [ direction: AppUtils.getCurrentDirection(context),
HtmlContentViewerOnWeb( contentPadding: 0,
key: ValueKey(tag), useDefaultFont: true,
widthContent: constraints.maxWidth, scrollController: scrollController,
heightContent: min( enableQuoteToggle: isInsideThreadDetailView,
constraints.maxHeight,
EmailViewStyles.initialHtmlViewHeight,
),
contentHtml: allEmailContents,
mailtoDelegate: controller.openMailToLink,
direction: AppUtils.getCurrentDirection(context),
contentPadding: 0,
useDefaultFont: true,
scrollController: scrollController,
enableQuoteToggle: isInsideThreadDetailView,
),
if (controller.mailboxDashBoardController.isDisplayedOverlayViewOnIFrame)
Positioned.fill(
child: PointerInterceptor(
child: const SizedBox.expand(),
),
),
],
);
});
}),
), ),
); );
} else if (PlatformInfo.isIOS) { } else if (PlatformInfo.isIOS) {
@@ -442,23 +439,21 @@ class EmailView extends GetWidget<SingleEmailController> {
vertical: EmailViewStyles.mobileContentVerticalMargin, vertical: EmailViewStyles.mobileContentVerticalMargin,
horizontal: EmailViewStyles.mobileContentHorizontalMargin, horizontal: EmailViewStyles.mobileContentHorizontalMargin,
), ),
child: LayoutBuilder(builder: (context, constraints) { child: HtmlContentViewer(
return HtmlContentViewer( key: controller.htmlContentViewKey,
key: controller.htmlContentViewKey, contentHtml: allEmailContents,
contentHtml: allEmailContents, initialWidth: bodyConstraints.maxWidth,
initialWidth: constraints.maxWidth, direction: AppUtils.getCurrentDirection(context),
direction: AppUtils.getCurrentDirection(context), contentPadding: 0,
contentPadding: 0, useDefaultFont: true,
useDefaultFont: true, maxHtmlContentHeight: ConstantsUI.htmlContentMaxHeight,
maxHtmlContentHeight: ConstantsUI.htmlContentMaxHeight, onMailtoDelegateAction: controller.openMailToLink,
onMailtoDelegateAction: controller.openMailToLink, onHtmlContentClippedAction: controller.onHtmlContentClippedAction,
onHtmlContentClippedAction: controller.onHtmlContentClippedAction, onScrollHorizontalEnd: controller.onScrollHorizontalEnd,
onScrollHorizontalEnd: controller.onScrollHorizontalEnd, keepAlive: isInsideThreadDetailView,
keepAlive: isInsideThreadDetailView, // TODO: Change this to [enableQuoteToggle: isInsideThreadDetailView,] when upgrade to Flutter 3.27.4
// TODO: Change this to [enableQuoteToggle: isInsideThreadDetailView,] when upgrade to Flutter 3.27.4 enableQuoteToggle: false,
enableQuoteToggle: false, ),
);
}),
), ),
Obx(() { Obx(() {
if (controller.isEmailContentClipped.isTrue) { if (controller.isEmailContentClipped.isTrue) {
@@ -484,20 +479,18 @@ class EmailView extends GetWidget<SingleEmailController> {
vertical: EmailViewStyles.mobileContentVerticalMargin, vertical: EmailViewStyles.mobileContentVerticalMargin,
horizontal: EmailViewStyles.mobileContentHorizontalMargin horizontal: EmailViewStyles.mobileContentHorizontalMargin
), ),
child: LayoutBuilder(builder: (context, constraints) { child: HtmlContentViewer(
return HtmlContentViewer( key: controller.htmlContentViewKey,
key: controller.htmlContentViewKey, contentHtml: allEmailContents,
contentHtml: allEmailContents, initialWidth: bodyConstraints.maxWidth,
initialWidth: constraints.maxWidth, direction: AppUtils.getCurrentDirection(context),
direction: AppUtils.getCurrentDirection(context), contentPadding: 0,
contentPadding: 0, useDefaultFont: true,
useDefaultFont: true, onMailtoDelegateAction: controller.openMailToLink,
onMailtoDelegateAction: controller.openMailToLink, keepAlive: isInsideThreadDetailView,
keepAlive: isInsideThreadDetailView, enableQuoteToggle: isInsideThreadDetailView,
enableQuoteToggle: isInsideThreadDetailView, onScrollHorizontalEnd: controller.onScrollHorizontalEnd,
onScrollHorizontalEnd: controller.onScrollHorizontalEnd, )
);
})
); );
} }
} else { } else {
@@ -14,7 +14,6 @@ class EmailViewStyles {
static const EdgeInsetsGeometry emailContentPadding = static const EdgeInsetsGeometry emailContentPadding =
EdgeInsetsDirectional.only( EdgeInsetsDirectional.only(
start: 16, start: 16,
bottom: 16,
end: 16, end: 16,
top: 8, top: 8,
); );