TF-2531 Fix cannot see all recipients list if email have a lot of recipients

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2024-02-01 10:16:37 +07:00
committed by Dat PHAM HOANG
parent 0247b7782d
commit dfd62d5ee4
3 changed files with 153 additions and 107 deletions
+112 -101
View File
@@ -2,6 +2,7 @@ import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/presentation/views/button/tmail_button_widget.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';
import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart'; import 'package:core/presentation/views/html_viewer/html_content_viewer_widget.dart';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/direction_utils.dart'; import 'package:core/utils/direction_utils.dart';
import 'package:core/utils/platform_info.dart'; import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -123,115 +124,123 @@ class EmailView extends GetWidget<SingleEmailController> {
} }
}), }),
Expanded( Expanded(
child: Obx(() { child: LayoutBuilder(builder: (context, constraints) {
if (controller.emailSupervisorController.supportedPageView.isTrue) { log('EmailView::build: EMAIL_BODY_MAX_HEIGHT = ${constraints.maxHeight}');
final currentListEmail = controller.emailSupervisorController.currentListEmail; return Obx(() {
return PageView.builder( if (controller.emailSupervisorController.supportedPageView.isTrue) {
physics: controller.emailSupervisorController.scrollPhysicsPageView.value, final currentListEmail = controller.emailSupervisorController.currentListEmail;
itemCount: currentListEmail.length, return PageView.builder(
allowImplicitScrolling: true, physics: controller.emailSupervisorController.scrollPhysicsPageView.value,
controller: controller.emailSupervisorController.pageController, itemCount: currentListEmail.length,
onPageChanged: controller.emailSupervisorController.onPageChanged, allowImplicitScrolling: true,
itemBuilder: (context, index) { controller: controller.emailSupervisorController.pageController,
final currentEmail = currentListEmail[index]; onPageChanged: controller.emailSupervisorController.onPageChanged,
if (PlatformInfo.isMobile) { itemBuilder: (context, index) {
return SingleChildScrollView( final currentEmail = currentListEmail[index];
physics : const ClampingScrollPhysics(), if (PlatformInfo.isMobile) {
child: Container( return SingleChildScrollView(
width: double.infinity, physics : const ClampingScrollPhysics(),
alignment: Alignment.center, child: Container(
color: Colors.white, width: double.infinity,
child: Obx(() => _buildEmailMessage( alignment: Alignment.center,
context: context, color: Colors.white,
presentationEmail: currentEmail, child: Obx(() => _buildEmailMessage(
calendarEvent: controller.calendarEvent.value, context: context,
)) presentationEmail: currentEmail,
) calendarEvent: controller.calendarEvent.value,
); maxBodyHeight: constraints.maxHeight
} else { ))
return Obx(() { )
final calendarEvent = controller.calendarEvent.value; );
if (currentEmail.hasCalendarEvent && calendarEvent != null) { } else {
return Padding( return Obx(() {
padding: const EdgeInsetsDirectional.symmetric(horizontal: 4), final calendarEvent = controller.calendarEvent.value;
child: ScrollbarListView( if (currentEmail.hasCalendarEvent && calendarEvent != null) {
scrollController: controller.emailContentScrollController, return Padding(
child: SingleChildScrollView( padding: const EdgeInsetsDirectional.symmetric(horizontal: 4),
physics : const ClampingScrollPhysics(), child: ScrollbarListView(
controller: controller.emailContentScrollController, scrollController: controller.emailContentScrollController,
child: Container( child: SingleChildScrollView(
width: double.infinity, physics : const ClampingScrollPhysics(),
alignment: Alignment.center, controller: controller.emailContentScrollController,
color: Colors.white, child: Container(
child: _buildEmailMessage( width: double.infinity,
context: context, alignment: Alignment.center,
presentationEmail: currentEmail, color: Colors.white,
calendarEvent: calendarEvent, child: _buildEmailMessage(
emailAddressSender: currentEmail.listEmailAddressSender.getListAddress(), context: context,
presentationEmail: currentEmail,
calendarEvent: calendarEvent,
emailAddressSender: currentEmail.listEmailAddressSender.getListAddress(),
)
) )
) ),
), ),
), );
); } else {
} else { return _buildEmailMessage(
return _buildEmailMessage( context: context,
context: context, presentationEmail: currentEmail,
presentationEmail: currentEmail, maxBodyHeight: constraints.maxHeight
); );
} }
}); });
}
} }
}
);
} else {
if (PlatformInfo.isMobile) {
return SingleChildScrollView(
physics : const ClampingScrollPhysics(),
child: Container(
width: double.infinity,
alignment: Alignment.center,
color: Colors.white,
child: Obx(() => _buildEmailMessage(
context: context,
presentationEmail: currentEmail,
calendarEvent: controller.calendarEvent.value,
))
)
); );
} else { } else {
return Obx(() { if (PlatformInfo.isMobile) {
final calendarEvent = controller.calendarEvent.value; return SingleChildScrollView(
if (currentEmail.hasCalendarEvent && calendarEvent != null) { physics : const ClampingScrollPhysics(),
return Padding( child: Container(
padding: const EdgeInsetsDirectional.symmetric(horizontal: 4), width: double.infinity,
child: ScrollbarListView( alignment: Alignment.center,
scrollController: controller.emailContentScrollController, color: Colors.white,
child: SingleChildScrollView( child: Obx(() => _buildEmailMessage(
physics : const ClampingScrollPhysics(), context: context,
controller: controller.emailContentScrollController, presentationEmail: currentEmail,
child: Container( calendarEvent: controller.calendarEvent.value,
width: double.infinity, maxBodyHeight: constraints.maxHeight
alignment: Alignment.center, ))
color: Colors.white, )
child: _buildEmailMessage( );
context: context, } else {
presentationEmail: currentEmail, return Obx(() {
calendarEvent: calendarEvent, final calendarEvent = controller.calendarEvent.value;
emailAddressSender: currentEmail.listEmailAddressSender.getListAddress(), if (currentEmail.hasCalendarEvent && calendarEvent != null) {
return Padding(
padding: const EdgeInsetsDirectional.symmetric(horizontal: 4),
child: ScrollbarListView(
scrollController: controller.emailContentScrollController,
child: SingleChildScrollView(
physics : const ClampingScrollPhysics(),
controller: controller.emailContentScrollController,
child: Container(
width: double.infinity,
alignment: Alignment.center,
color: Colors.white,
child: _buildEmailMessage(
context: context,
presentationEmail: currentEmail,
calendarEvent: calendarEvent,
emailAddressSender: currentEmail.listEmailAddressSender.getListAddress(),
maxBodyHeight: constraints.maxHeight
)
) )
) ),
), ),
), );
); } else {
} else { return _buildEmailMessage(
return _buildEmailMessage( context: context,
context: context, presentationEmail: currentEmail,
presentationEmail: currentEmail, maxBodyHeight: constraints.maxHeight
); );
} }
}); });
}
} }
} });
}), }),
), ),
EmailViewBottomBarWidget( EmailViewBottomBarWidget(
@@ -305,6 +314,7 @@ class EmailView extends GetWidget<SingleEmailController> {
required PresentationEmail presentationEmail, required PresentationEmail presentationEmail,
CalendarEvent? calendarEvent, CalendarEvent? calendarEvent,
List<String>? emailAddressSender, List<String>? emailAddressSender,
double? maxBodyHeight,
}) { }) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -315,6 +325,7 @@ class EmailView extends GetWidget<SingleEmailController> {
imagePaths: controller.imagePaths, imagePaths: controller.imagePaths,
responsiveUtils: controller.responsiveUtils, responsiveUtils: controller.responsiveUtils,
emailUnsubscribe: controller.emailUnsubscribe.value, emailUnsubscribe: controller.emailUnsubscribe.value,
maxBodyHeight: maxBodyHeight,
openEmailAddressDetailAction: controller.openEmailAddressDialog, openEmailAddressDetailAction: controller.openEmailAddressDialog,
onEmailActionClick: (presentationEmail, actionType) => controller.handleEmailAction(context, presentationEmail, actionType), onEmailActionClick: (presentationEmail, actionType) => controller.handleEmailAction(context, presentationEmail, actionType),
)), )),
@@ -5,6 +5,7 @@ import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/style_utils.dart'; import 'package:core/presentation/utils/style_utils.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/utils/direction_utils.dart'; import 'package:core/utils/direction_utils.dart';
import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
@@ -14,6 +15,7 @@ import 'package:model/extensions/email_address_extension.dart';
import 'package:model/extensions/list_email_address_extension.dart'; import 'package:model/extensions/list_email_address_extension.dart';
import 'package:model/extensions/presentation_email_extension.dart'; import 'package:model/extensions/presentation_email_extension.dart';
import 'package:tmail_ui_user/features/base/widget/material_text_button.dart'; import 'package:tmail_ui_user/features/base/widget/material_text_button.dart';
import 'package:tmail_ui_user/features/base/widget/scrollbar_list_view.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/prefix_email_address_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/prefix_email_address_extension.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/email_sender_builder.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/email_sender_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -23,12 +25,14 @@ class EmailReceiverWidget extends StatefulWidget {
final PresentationEmail emailSelected; final PresentationEmail emailSelected;
final double maxWidth; final double maxWidth;
final double? maxHeight;
final OnOpenEmailAddressDetailAction? openEmailAddressDetailAction; final OnOpenEmailAddressDetailAction? openEmailAddressDetailAction;
const EmailReceiverWidget({ const EmailReceiverWidget({
Key? key, Key? key,
required this.emailSelected, required this.emailSelected,
this.maxWidth = 200, this.maxWidth = 200,
this.maxHeight,
this.openEmailAddressDetailAction, this.openEmailAddressDetailAction,
}) : super(key: key); }) : super(key: key);
@@ -39,9 +43,11 @@ class EmailReceiverWidget extends StatefulWidget {
class _EmailReceiverWidgetState extends State<EmailReceiverWidget> { class _EmailReceiverWidgetState extends State<EmailReceiverWidget> {
static const double _maxSizeFullDisplayEmailAddressArrowDownButton = 50.0; static const double _maxSizeFullDisplayEmailAddressArrowDownButton = 50.0;
static const double _offsetTop = 100.0;
final _imagePaths = Get.find<ImagePaths>(); final _imagePaths = Get.find<ImagePaths>();
final _responsiveUtils = Get.find<ResponsiveUtils>(); final _responsiveUtils = Get.find<ResponsiveUtils>();
final _scrollController = ScrollController();
bool _isDisplayAll = false; bool _isDisplayAll = false;
@@ -54,12 +60,32 @@ class _EmailReceiverWidgetState extends State<EmailReceiverWidget> {
padding: EdgeInsets.only(top: _isDisplayAll padding: EdgeInsets.only(top: _isDisplayAll
? DirectionUtils.isDirectionRTLByLanguage(context) ? 3 : 5.5 ? DirectionUtils.isDirectionRTLByLanguage(context) ? 3 : 5.5
: 0), : 0),
child: _buildEmailAddressOfReceiver( child: PlatformInfo.isWeb
context, ? Container(
widget.emailSelected, constraints: BoxConstraints(
_isDisplayAll, maxHeight: _isDisplayAll && widget.maxHeight != null
widget.maxWidth ? widget.maxHeight! / 2 - _offsetTop
), : double.infinity
),
child: ScrollbarListView(
scrollController: _scrollController,
child: SingleChildScrollView(
controller: _scrollController,
child: _buildEmailAddressOfReceiver(
context,
widget.emailSelected,
_isDisplayAll,
widget.maxWidth
),
),
),
)
: _buildEmailAddressOfReceiver(
context,
widget.emailSelected,
_isDisplayAll,
widget.maxWidth
),
)), )),
if (_isDisplayAll) if (_isDisplayAll)
Padding( Padding(
@@ -244,4 +270,10 @@ class _EmailReceiverWidgetState extends State<EmailReceiverWidget> {
return maxWidth * 3/4; return maxWidth * 3/4;
} }
} }
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
} }
@@ -22,6 +22,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
final EmailUnsubscribe? emailUnsubscribe; final EmailUnsubscribe? emailUnsubscribe;
final OnOpenEmailAddressDetailAction? openEmailAddressDetailAction; final OnOpenEmailAddressDetailAction? openEmailAddressDetailAction;
final OnEmailActionClick? onEmailActionClick; final OnEmailActionClick? onEmailActionClick;
final double? maxBodyHeight;
const InformationSenderAndReceiverBuilder({ const InformationSenderAndReceiverBuilder({
Key? key, Key? key,
@@ -29,6 +30,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
required this.responsiveUtils, required this.responsiveUtils,
required this.imagePaths, required this.imagePaths,
required this.emailUnsubscribe, required this.emailUnsubscribe,
this.maxBodyHeight,
this.openEmailAddressDetailAction, this.openEmailAddressDetailAction,
this.onEmailActionClick, this.onEmailActionClick,
}) : super(key: key); }) : super(key: key);
@@ -88,6 +90,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
EmailReceiverWidget( EmailReceiverWidget(
emailSelected: emailSelected, emailSelected: emailSelected,
maxWidth: constraints.maxWidth, maxWidth: constraints.maxWidth,
maxHeight: maxBodyHeight,
openEmailAddressDetailAction: openEmailAddressDetailAction, openEmailAddressDetailAction: openEmailAddressDetailAction,
) )
] ]