Change order of attachment and mail body on mobile

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-07-09 11:52:29 +07:00
committed by Dat H. Pham
parent 5e3f4458c5
commit 296065c0b7
28 changed files with 501 additions and 418 deletions
@@ -1,4 +1,5 @@
import 'package:core/presentation/action/action_callback_define.dart';
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart';
@@ -8,7 +9,6 @@ import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:model/email/attachment.dart';
import 'package:model/extensions/list_attachment_extension.dart';
import 'package:tmail_ui_user/features/email/presentation/styles/email_attachments_styles.dart';
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_item_widget.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/attachments_info.dart';
@@ -44,135 +44,225 @@ class EmailAttachmentsWidget extends StatelessWidget {
this.singleEmailControllerTag,
});
Widget _buildMoreAttachmentButton(
BuildContext context,
int hideItemsCount, {
EdgeInsetsGeometry? padding,
EdgeInsetsGeometry? margin,
}) {
return TMailButtonWidget(
text: AppLocalizations.of(context).moreAttachments(hideItemsCount),
backgroundColor: Colors.transparent,
borderRadius: EmailAttachmentsStyles.buttonBorderRadius,
padding: padding,
maxWidth: EmailAttachmentsStyles.buttonMoreMaxWidth,
margin: margin,
textStyle: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: EmailAttachmentsStyles.buttonMoreAttachmentsTextSize,
color: EmailAttachmentsStyles.buttonMoreAttachmentsTextColor,
fontWeight: EmailAttachmentsStyles.buttonMoreAttachmentsFontWeight,
),
maxLines: 1,
onTapActionCallback: onTapShowAllAttachmentFile,
);
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
final attachmentDisplayed = EmailUtils.getAttachmentDisplayed(
context: context,
maxWidth: constraints.maxWidth
- EmailAttachmentsStyles.padding.horizontal
- EmailAttachmentsStyles.listSpace * 2,
platformIsMobile: PlatformInfo.isMobile,
attachments: attachments,
responsiveUtils: responsiveUtils,
final attachmentRecord = _getDisplayedAndHiddenAttachment(
context,
constraints.maxWidth,
);
int hideItemsCount = attachments.length - attachmentDisplayed.length;
if (hideItemsCount > 999) {
hideItemsCount = 999;
}
return Padding(
padding: EmailAttachmentsStyles.padding,
child: Column(
final attachmentHeader = AttachmentsInfo(
imagePaths: imagePaths,
numberOfAttachments: attachments.length,
totalSizeInfo: filesize(attachments.totalSize, 1),
responsiveUtils: responsiveUtils,
onTapShowAllAttachmentFile: onTapShowAllAttachmentFile,
onTapDownloadAllButton: showDownloadAllAttachmentsButton
? onTapDownloadAllButton
: null,
);
late Widget attachmentWidget;
if (responsiveUtils.isMobile(context)) {
attachmentWidget = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AttachmentsInfo(
imagePaths: imagePaths,
numberOfAttachments: attachments.length,
totalSizeInfo: filesize(attachments.totalSize, 1),
responsiveUtils: responsiveUtils,
onTapShowAllAttachmentFile: onTapShowAllAttachmentFile,
downloadAllEnabled: showDownloadAllAttachmentsButton,
onTapDownloadAllButton: onTapDownloadAllButton,
Padding(
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
child: attachmentHeader,
),
const SizedBox(height: EmailAttachmentsStyles.marginHeader),
Row(
crossAxisAlignment: responsiveUtils.isMobile(context)
? CrossAxisAlignment.end
: CrossAxisAlignment.center,
children: [
Flexible(
child: Wrap(
spacing: EmailAttachmentsStyles.listSpace,
runSpacing: EmailAttachmentsStyles.listSpace,
children: attachmentDisplayed.map((attachment) {
if (PlatformInfo.isWeb) {
return DraggableAttachmentItemWidget(
attachment: attachment,
onDragStarted: onDragStarted,
onDragEnd: onDragEnd,
downloadAttachmentAction: downloadAttachmentAction,
viewAttachmentAction: viewAttachmentAction,
singleEmailControllerTag: singleEmailControllerTag,
);
} else {
return AttachmentItemWidget(
attachment: attachment,
downloadAttachmentAction: downloadAttachmentAction,
viewAttachmentAction: viewAttachmentAction,
singleEmailControllerTag: singleEmailControllerTag,
);
}
}).toList(),
),
),
if (hideItemsCount > 0 && !responsiveUtils.isMobile(context))
_buildMoreAttachmentButton(
context,
hideItemsCount,
padding: EmailAttachmentsStyles.buttonPadding,
margin: EmailAttachmentsStyles.moreButtonMargin,
),
]
const SizedBox(height: 4),
Padding(
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
child: Column(
children: attachmentRecord.displayedAttachments.map((attachment) {
return AttachmentItemWidget(
attachment: attachment,
imagePaths: imagePaths,
downloadAttachmentAction: downloadAttachmentAction,
viewAttachmentAction: viewAttachmentAction,
singleEmailControllerTag: singleEmailControllerTag,
);
}).toList(),
),
),
const SizedBox(height: EmailAttachmentsStyles.marginHeader),
if (responsiveUtils.isMobile(context))
Row(
children: [
if (hideItemsCount > 0)
_buildMoreAttachmentButton(
context,
hideItemsCount,
padding: EmailAttachmentsStyles.mobileButtonPadding,
margin: EmailAttachmentsStyles.mobileMoreButtonMargin,
const SizedBox(height: 12),
if (attachmentRecord.hiddenItemsCount > 0 &&
showDownloadAllAttachmentsButton)
Padding(
padding: const EdgeInsetsDirectional.symmetric(horizontal: 8),
child: Row(
children: [
TMailButtonWidget.fromText(
text: AppLocalizations.of(context).moreAttachments(
attachmentRecord.hiddenItemsCount,
),
backgroundColor: Colors.transparent,
borderRadius: 5,
maxWidth: 120,
maxLines: 1,
textStyle: ThemeUtils.textStyleM3TitleSmall,
padding: const EdgeInsets.symmetric(
vertical: 3,
horizontal: 5,
),
onTapActionCallback: onTapShowAllAttachmentFile,
),
const Spacer(),
if (showDownloadAllAttachmentsButton)
TMailButtonWidget(
text: AppLocalizations.of(context).downloadAll,
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: TMailButtonWidget(
text: AppLocalizations.of(context).archiveAndDownload,
icon: imagePaths.icDownloadAll,
iconSize: 20,
iconColor: AppColor.steelGrayA540,
iconAlignment: TextDirection.rtl,
backgroundColor: Colors.transparent,
borderRadius: 5,
mainAxisSize: MainAxisSize.min,
maxLines: 1,
flexibleText: true,
padding: const EdgeInsets.symmetric(
vertical: 3,
horizontal: 5,
),
textStyle: ThemeUtils.textStyleBodyBody1().copyWith(
color: AppColor.steelGray400,
),
onTapActionCallback: onTapDownloadAllButton,
),
),
],
),
),
],
),
)
else if (attachmentRecord.hiddenItemsCount > 0)
TMailButtonWidget.fromText(
text: AppLocalizations.of(context).moreAttachments(
attachmentRecord.hiddenItemsCount,
),
backgroundColor: Colors.transparent,
borderRadius: 5,
maxLines: 1,
textStyle: ThemeUtils.textStyleM3TitleSmall,
padding: const EdgeInsets.symmetric(
vertical: 3,
horizontal: 5,
),
margin: const EdgeInsetsDirectional.symmetric(horizontal: 8),
onTapActionCallback: onTapShowAllAttachmentFile,
)
else if (showDownloadAllAttachmentsButton)
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Flexible(
child: TMailButtonWidget(
text: AppLocalizations.of(context).archiveAndDownload,
icon: imagePaths.icDownloadAll,
iconSize: 20,
iconColor: AppColor.steelGrayA540,
iconAlignment: TextDirection.rtl,
backgroundColor: Colors.transparent,
borderRadius: EmailAttachmentsStyles.buttonBorderRadius,
padding: EmailAttachmentsStyles.mobileButtonPadding,
textStyle: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontSize: EmailAttachmentsStyles.buttonTextSize,
color: EmailAttachmentsStyles.buttonTextColor,
fontWeight: EmailAttachmentsStyles.buttonFontWeight
),
maxWidth: EmailAttachmentsStyles.buttonDownloadAllMaxWidth,
maxLines: 1,
borderRadius: 5,
mainAxisSize: MainAxisSize.min,
maxLines: 1,
flexibleText: true,
padding: const EdgeInsets.symmetric(
vertical: 3,
horizontal: 5,
),
margin: const EdgeInsetsDirectional.symmetric(horizontal: 8),
textStyle: ThemeUtils.textStyleBodyBody1().copyWith(
color: AppColor.steelGray400,
),
onTapActionCallback: onTapDownloadAllButton,
),
]
),
],
),
],
),
);
} else {
attachmentWidget = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
child: attachmentHeader,
),
const SizedBox(height: 4),
Padding(
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
child: Wrap(
spacing: 8,
runSpacing: 8,
children: attachmentRecord.displayedAttachments.map((attachment) {
if (responsiveUtils.isDesktop(context)) {
return DraggableAttachmentItemWidget(
attachment: attachment,
imagePaths: imagePaths,
onDragStarted: onDragStarted,
onDragEnd: onDragEnd,
downloadAttachmentAction: downloadAttachmentAction,
viewAttachmentAction: viewAttachmentAction,
singleEmailControllerTag: singleEmailControllerTag,
);
} else {
return AttachmentItemWidget(
attachment: attachment,
imagePaths: imagePaths,
width: 260,
downloadAttachmentAction: downloadAttachmentAction,
viewAttachmentAction: viewAttachmentAction,
singleEmailControllerTag: singleEmailControllerTag,
);
}
}).toList(),
),
),
],
);
}
return Padding(
padding: const EdgeInsetsDirectional.only(top: 12, bottom: 24),
child: attachmentWidget,
);
});
}
({List<Attachment> displayedAttachments, int hiddenItemsCount})
_getDisplayedAndHiddenAttachment(BuildContext context, double maxWidth) {
const itemSpace = 8.0;
const itemHorizontalPadding = 24;
final maxWidthDesktop = maxWidth - itemHorizontalPadding - itemSpace * 2;
final displayedAttachments = EmailUtils.getAttachmentDisplayed(
context: context,
maxWidth: maxWidthDesktop,
platformIsMobile: PlatformInfo.isMobile,
attachments: attachments,
responsiveUtils: responsiveUtils,
);
int hiddenItemsCount = attachments.length - displayedAttachments.length;
if (hiddenItemsCount > 999) {
hiddenItemsCount = 999;
} else if (hiddenItemsCount < 0) {
hiddenItemsCount = 0;
}
return (
displayedAttachments: displayedAttachments,
hiddenItemsCount: hiddenItemsCount,
);
}
}