Change order of attachment and mail body on desktop
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -1,9 +1,7 @@
|
|||||||
import 'package:core/presentation/state/failure.dart';
|
import 'package:core/presentation/state/failure.dart';
|
||||||
import 'package:core/presentation/state/success.dart';
|
import 'package:core/presentation/state/success.dart';
|
||||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
|
||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:core/utils/mail/mail_address.dart';
|
import 'package:core/utils/mail/mail_address.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:get/get_utils/src/get_utils/get_utils.dart';
|
import 'package:get/get_utils/src/get_utils/get_utils.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:http_parser/http_parser.dart';
|
import 'package:http_parser/http_parser.dart';
|
||||||
@@ -23,6 +21,10 @@ import 'package:tmail_ui_user/main/error/capability_validator.dart';
|
|||||||
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||||
|
|
||||||
class EmailUtils {
|
class EmailUtils {
|
||||||
|
static const double desktopItemMaxWidth = 260;
|
||||||
|
static const double desktopMoreButtonMaxWidth = 70;
|
||||||
|
static const double maxMobileVisibleAttachments = 3;
|
||||||
|
|
||||||
EmailUtils._();
|
EmailUtils._();
|
||||||
|
|
||||||
static Properties getPropertiesForEmailGetMethod(Session session, AccountId accountId) {
|
static Properties getPropertiesForEmailGetMethod(Session session, AccountId accountId) {
|
||||||
@@ -237,29 +239,29 @@ class EmailUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static List<Attachment> getAttachmentDisplayed({
|
static List<Attachment> getAttachmentDisplayed({
|
||||||
required BuildContext context,
|
|
||||||
required double maxWidth,
|
required double maxWidth,
|
||||||
required bool platformIsMobile,
|
|
||||||
required List<Attachment> attachments,
|
required List<Attachment> attachments,
|
||||||
required ResponsiveUtils responsiveUtils,
|
required bool isMobile,
|
||||||
}) {
|
}) {
|
||||||
if (attachments.isEmpty) return [];
|
if (attachments.isEmpty) return [];
|
||||||
|
|
||||||
final bool isMobile = responsiveUtils.isMobile(context);
|
|
||||||
|
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
return attachments.length <= 3 ? attachments : attachments.sublist(0, 3);
|
return attachments.length <= maxMobileVisibleAttachments
|
||||||
|
? attachments
|
||||||
|
: attachments.sublist(0, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
const double maxWidthItem = 260;
|
final displayedCount = maxWidth ~/ desktopItemMaxWidth;
|
||||||
const double buttonMoreMaxWidth = 120;
|
if (displayedCount == attachments.length) {
|
||||||
|
return attachments;
|
||||||
|
} else {
|
||||||
|
final int possibleDisplayedCount =
|
||||||
|
((maxWidth - desktopMoreButtonMaxWidth) ~/ desktopItemMaxWidth)
|
||||||
|
.clamp(0, attachments.length);
|
||||||
|
|
||||||
final int possibleDisplayedCount =
|
return possibleDisplayedCount == 0
|
||||||
((maxWidth - buttonMoreMaxWidth) ~/ maxWidthItem)
|
? [attachments.first]
|
||||||
.clamp(0, attachments.length);
|
: attachments.sublist(0, possibleDisplayedCount);
|
||||||
|
}
|
||||||
return possibleDisplayedCount == 0
|
|
||||||
? [attachments.first]
|
|
||||||
: attachments.sublist(0, possibleDisplayedCount);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,7 @@ class AttachmentItemWidget extends StatelessWidget {
|
|||||||
final Attachment attachment;
|
final Attachment attachment;
|
||||||
final ImagePaths imagePaths;
|
final ImagePaths imagePaths;
|
||||||
final double? width;
|
final double? width;
|
||||||
|
final EdgeInsetsGeometry? margin;
|
||||||
final OnDownloadAttachmentFileAction? downloadAttachmentAction;
|
final OnDownloadAttachmentFileAction? downloadAttachmentAction;
|
||||||
final OnViewAttachmentFileAction? viewAttachmentAction;
|
final OnViewAttachmentFileAction? viewAttachmentAction;
|
||||||
final String? singleEmailControllerTag;
|
final String? singleEmailControllerTag;
|
||||||
@@ -31,6 +32,7 @@ class AttachmentItemWidget extends StatelessWidget {
|
|||||||
required this.attachment,
|
required this.attachment,
|
||||||
required this.imagePaths,
|
required this.imagePaths,
|
||||||
this.width,
|
this.width,
|
||||||
|
this.margin,
|
||||||
this.downloadAttachmentAction,
|
this.downloadAttachmentAction,
|
||||||
this.viewAttachmentAction,
|
this.viewAttachmentAction,
|
||||||
this.singleEmailControllerTag,
|
this.singleEmailControllerTag,
|
||||||
@@ -124,7 +126,7 @@ class AttachmentItemWidget extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
width: width,
|
width: width,
|
||||||
margin: const EdgeInsets.only(top: 8),
|
margin: margin,
|
||||||
onTapActionCallback:
|
onTapActionCallback:
|
||||||
isLoading ? null : () => _onViewOrDownloadAction(attachment),
|
isLoading ? null : () => _onViewOrDownloadAction(attachment),
|
||||||
child: bodyItemWidget,
|
child: bodyItemWidget,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class DraggableAttachmentItemWidget extends StatelessWidget{
|
|||||||
|
|
||||||
final Attachment attachment;
|
final Attachment attachment;
|
||||||
final ImagePaths imagePaths;
|
final ImagePaths imagePaths;
|
||||||
|
final double? width;
|
||||||
final OnDragAttachmentStarted? onDragStarted;
|
final OnDragAttachmentStarted? onDragStarted;
|
||||||
final OnDragAttachmentEnd? onDragEnd;
|
final OnDragAttachmentEnd? onDragEnd;
|
||||||
final OnDownloadAttachmentFileAction? downloadAttachmentAction;
|
final OnDownloadAttachmentFileAction? downloadAttachmentAction;
|
||||||
@@ -22,6 +23,7 @@ class DraggableAttachmentItemWidget extends StatelessWidget{
|
|||||||
Key? key,
|
Key? key,
|
||||||
required this.attachment,
|
required this.attachment,
|
||||||
required this.imagePaths,
|
required this.imagePaths,
|
||||||
|
this.width,
|
||||||
this.onDragStarted,
|
this.onDragStarted,
|
||||||
this.onDragEnd,
|
this.onDragEnd,
|
||||||
this.downloadAttachmentAction,
|
this.downloadAttachmentAction,
|
||||||
@@ -39,6 +41,7 @@ class DraggableAttachmentItemWidget extends StatelessWidget{
|
|||||||
child: AttachmentItemWidget(
|
child: AttachmentItemWidget(
|
||||||
attachment: attachment,
|
attachment: attachment,
|
||||||
imagePaths: imagePaths,
|
imagePaths: imagePaths,
|
||||||
|
width: width,
|
||||||
downloadAttachmentAction: downloadAttachmentAction,
|
downloadAttachmentAction: downloadAttachmentAction,
|
||||||
viewAttachmentAction: viewAttachmentAction,
|
viewAttachmentAction: viewAttachmentAction,
|
||||||
singleEmailControllerTag: singleEmailControllerTag,
|
singleEmailControllerTag: singleEmailControllerTag,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import 'package:core/presentation/resources/image_paths.dart';
|
|||||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||||
import 'package:core/presentation/utils/theme_utils.dart';
|
import 'package:core/presentation/utils/theme_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/platform_info.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:filesize/filesize.dart';
|
import 'package:filesize/filesize.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:model/email/attachment.dart';
|
import 'package:model/email/attachment.dart';
|
||||||
@@ -46,41 +46,46 @@ class EmailAttachmentsWidget extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
final attachmentHeader = AttachmentsInfo(
|
||||||
final attachmentRecord = _getDisplayedAndHiddenAttachment(
|
imagePaths: imagePaths,
|
||||||
context,
|
numberOfAttachments: attachments.length,
|
||||||
constraints.maxWidth,
|
totalSizeInfo: filesize(attachments.totalSize, 1),
|
||||||
);
|
responsiveUtils: responsiveUtils,
|
||||||
|
onTapShowAllAttachmentFile: onTapShowAllAttachmentFile,
|
||||||
final attachmentHeader = AttachmentsInfo(
|
onTapDownloadAllButton: showDownloadAllAttachmentsButton
|
||||||
imagePaths: imagePaths,
|
|
||||||
numberOfAttachments: attachments.length,
|
|
||||||
totalSizeInfo: filesize(attachments.totalSize, 1),
|
|
||||||
responsiveUtils: responsiveUtils,
|
|
||||||
onTapShowAllAttachmentFile: onTapShowAllAttachmentFile,
|
|
||||||
onTapDownloadAllButton: showDownloadAllAttachmentsButton
|
|
||||||
? onTapDownloadAllButton
|
? onTapDownloadAllButton
|
||||||
: null,
|
: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (responsiveUtils.isMobile(context)) {
|
||||||
|
final attachmentRecord = _getDisplayedAndHiddenAttachment(
|
||||||
|
context,
|
||||||
|
responsiveUtils.getDeviceWidth(context),
|
||||||
);
|
);
|
||||||
|
final displayedAttachments = attachmentRecord.displayedAttachments;
|
||||||
|
final hiddenItemsCount = attachmentRecord.hiddenItemsCount;
|
||||||
|
|
||||||
late Widget attachmentWidget;
|
return Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.only(top: 12, bottom: 24),
|
||||||
if (responsiveUtils.isMobile(context)) {
|
child: Column(
|
||||||
attachmentWidget = Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
|
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
|
||||||
child: attachmentHeader,
|
child: attachmentHeader,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
|
padding: const EdgeInsetsDirectional.only(
|
||||||
|
start: 12,
|
||||||
|
end: 12,
|
||||||
|
top: 4,
|
||||||
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: attachmentRecord.displayedAttachments.map((attachment) {
|
children: displayedAttachments.map((attachment) {
|
||||||
return AttachmentItemWidget(
|
return AttachmentItemWidget(
|
||||||
attachment: attachment,
|
attachment: attachment,
|
||||||
imagePaths: imagePaths,
|
imagePaths: imagePaths,
|
||||||
|
margin: const EdgeInsets.only(top: 8),
|
||||||
downloadAttachmentAction: downloadAttachmentAction,
|
downloadAttachmentAction: downloadAttachmentAction,
|
||||||
viewAttachmentAction: viewAttachmentAction,
|
viewAttachmentAction: viewAttachmentAction,
|
||||||
singleEmailControllerTag: singleEmailControllerTag,
|
singleEmailControllerTag: singleEmailControllerTag,
|
||||||
@@ -89,15 +94,14 @@ class EmailAttachmentsWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
if (attachmentRecord.hiddenItemsCount > 0 &&
|
if (hiddenItemsCount > 0 && showDownloadAllAttachmentsButton)
|
||||||
showDownloadAllAttachmentsButton)
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsetsDirectional.symmetric(horizontal: 8),
|
padding: const EdgeInsetsDirectional.symmetric(horizontal: 8),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
TMailButtonWidget.fromText(
|
TMailButtonWidget.fromText(
|
||||||
text: AppLocalizations.of(context).moreAttachments(
|
text: AppLocalizations.of(context).moreAttachments(
|
||||||
attachmentRecord.hiddenItemsCount,
|
hiddenItemsCount,
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
@@ -117,7 +121,9 @@ class EmailAttachmentsWidget extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
child: TMailButtonWidget(
|
child: TMailButtonWidget(
|
||||||
text: AppLocalizations.of(context).archiveAndDownload,
|
text: AppLocalizations
|
||||||
|
.of(context)
|
||||||
|
.archiveAndDownload,
|
||||||
icon: imagePaths.icDownloadAll,
|
icon: imagePaths.icDownloadAll,
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
iconColor: AppColor.steelGrayA540,
|
iconColor: AppColor.steelGrayA540,
|
||||||
@@ -131,9 +137,8 @@ class EmailAttachmentsWidget extends StatelessWidget {
|
|||||||
vertical: 3,
|
vertical: 3,
|
||||||
horizontal: 5,
|
horizontal: 5,
|
||||||
),
|
),
|
||||||
textStyle: ThemeUtils.textStyleBodyBody1().copyWith(
|
textStyle: ThemeUtils.textStyleBodyBody1()
|
||||||
color: AppColor.steelGray400,
|
.copyWith(color: AppColor.steelGray400),
|
||||||
),
|
|
||||||
onTapActionCallback: onTapDownloadAllButton,
|
onTapActionCallback: onTapDownloadAllButton,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -143,10 +148,10 @@ class EmailAttachmentsWidget extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else if (attachmentRecord.hiddenItemsCount > 0)
|
else if (hiddenItemsCount > 0)
|
||||||
TMailButtonWidget.fromText(
|
TMailButtonWidget.fromText(
|
||||||
text: AppLocalizations.of(context).moreAttachments(
|
text: AppLocalizations.of(context).moreAttachments(
|
||||||
attachmentRecord.hiddenItemsCount,
|
hiddenItemsCount,
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
@@ -160,97 +165,127 @@ class EmailAttachmentsWidget extends StatelessWidget {
|
|||||||
onTapActionCallback: onTapShowAllAttachmentFile,
|
onTapActionCallback: onTapShowAllAttachmentFile,
|
||||||
)
|
)
|
||||||
else if (showDownloadAllAttachmentsButton)
|
else if (showDownloadAllAttachmentsButton)
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
child: TMailButtonWidget(
|
child: TMailButtonWidget(
|
||||||
text: AppLocalizations.of(context).archiveAndDownload,
|
text: AppLocalizations.of(context).archiveAndDownload,
|
||||||
icon: imagePaths.icDownloadAll,
|
icon: imagePaths.icDownloadAll,
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
iconColor: AppColor.steelGrayA540,
|
iconColor: AppColor.steelGrayA540,
|
||||||
iconAlignment: TextDirection.rtl,
|
iconAlignment: TextDirection.rtl,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
flexibleText: true,
|
flexibleText: true,
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 3,
|
vertical: 3,
|
||||||
horizontal: 5,
|
horizontal: 5,
|
||||||
|
),
|
||||||
|
margin: const EdgeInsetsDirectional.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
),
|
||||||
|
textStyle: ThemeUtils.textStyleBodyBody1().copyWith(
|
||||||
|
color: AppColor.steelGray400,
|
||||||
|
),
|
||||||
|
onTapActionCallback: onTapDownloadAllButton,
|
||||||
),
|
),
|
||||||
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,
|
|
||||||
);
|
);
|
||||||
});
|
} else {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.only(
|
||||||
|
start: 16,
|
||||||
|
end: 16,
|
||||||
|
top: 16,
|
||||||
|
bottom: 28,
|
||||||
|
),
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
final attachmentRecord = _getDisplayedAndHiddenAttachment(
|
||||||
|
context,
|
||||||
|
constraints.maxWidth,
|
||||||
|
);
|
||||||
|
final displayedAttachments = attachmentRecord.displayedAttachments;
|
||||||
|
final hiddenItemsCount = attachmentRecord.hiddenItemsCount;
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
|
||||||
|
child: attachmentHeader,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.only(
|
||||||
|
start: 12,
|
||||||
|
end: 12,
|
||||||
|
top: 12,
|
||||||
|
),
|
||||||
|
child: Wrap(
|
||||||
|
spacing: 8,
|
||||||
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
|
children: [
|
||||||
|
...displayedAttachments.map((attachment) {
|
||||||
|
if (responsiveUtils.isDesktop(context)) {
|
||||||
|
return DraggableAttachmentItemWidget(
|
||||||
|
attachment: attachment,
|
||||||
|
imagePaths: imagePaths,
|
||||||
|
width: EmailUtils.desktopItemMaxWidth,
|
||||||
|
onDragStarted: onDragStarted,
|
||||||
|
onDragEnd: onDragEnd,
|
||||||
|
downloadAttachmentAction: downloadAttachmentAction,
|
||||||
|
viewAttachmentAction: viewAttachmentAction,
|
||||||
|
singleEmailControllerTag: singleEmailControllerTag,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return AttachmentItemWidget(
|
||||||
|
attachment: attachment,
|
||||||
|
imagePaths: imagePaths,
|
||||||
|
width: EmailUtils.desktopItemMaxWidth,
|
||||||
|
downloadAttachmentAction: downloadAttachmentAction,
|
||||||
|
viewAttachmentAction: viewAttachmentAction,
|
||||||
|
singleEmailControllerTag: singleEmailControllerTag,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}).toList(),
|
||||||
|
if (hiddenItemsCount > 0)
|
||||||
|
TMailButtonWidget.fromText(
|
||||||
|
text: '+ $hiddenItemsCount',
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
borderRadius: 5,
|
||||||
|
maxWidth: EmailUtils.desktopMoreButtonMaxWidth,
|
||||||
|
maxLines: 1,
|
||||||
|
textStyle: ThemeUtils.textStyleM3TitleSmall,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 3,
|
||||||
|
horizontal: 5,
|
||||||
|
),
|
||||||
|
onTapActionCallback: onTapShowAllAttachmentFile,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
({List<Attachment> displayedAttachments, int hiddenItemsCount})
|
({List<Attachment> displayedAttachments, int hiddenItemsCount})
|
||||||
_getDisplayedAndHiddenAttachment(BuildContext context, double maxWidth) {
|
_getDisplayedAndHiddenAttachment(BuildContext context, double maxWidth) {
|
||||||
const itemSpace = 8.0;
|
|
||||||
const itemHorizontalPadding = 24;
|
|
||||||
final maxWidthDesktop = maxWidth - itemHorizontalPadding - itemSpace * 2;
|
|
||||||
|
|
||||||
final displayedAttachments = EmailUtils.getAttachmentDisplayed(
|
final displayedAttachments = EmailUtils.getAttachmentDisplayed(
|
||||||
context: context,
|
maxWidth: maxWidth,
|
||||||
maxWidth: maxWidthDesktop,
|
|
||||||
platformIsMobile: PlatformInfo.isMobile,
|
|
||||||
attachments: attachments,
|
attachments: attachments,
|
||||||
responsiveUtils: responsiveUtils,
|
isMobile: responsiveUtils.isMobile(context),
|
||||||
);
|
);
|
||||||
|
|
||||||
int hiddenItemsCount = attachments.length - displayedAttachments.length;
|
int hiddenItemsCount = attachments.length - displayedAttachments.length;
|
||||||
@@ -259,7 +294,7 @@ class EmailAttachmentsWidget extends StatelessWidget {
|
|||||||
} else if (hiddenItemsCount < 0) {
|
} else if (hiddenItemsCount < 0) {
|
||||||
hiddenItemsCount = 0;
|
hiddenItemsCount = 0;
|
||||||
}
|
}
|
||||||
|
log('EmailAttachmentsWidget::_getDisplayedAndHiddenAttachment: Displayed: ${displayedAttachments.length}, Hidden: $hiddenItemsCount');
|
||||||
return (
|
return (
|
||||||
displayedAttachments: displayedAttachments,
|
displayedAttachments: displayedAttachments,
|
||||||
hiddenItemsCount: hiddenItemsCount,
|
hiddenItemsCount: hiddenItemsCount,
|
||||||
|
|||||||
@@ -1,160 +1,88 @@
|
|||||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:mockito/annotations.dart';
|
|
||||||
import 'package:mockito/mockito.dart';
|
|
||||||
import 'package:model/email/attachment.dart';
|
import 'package:model/email/attachment.dart';
|
||||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||||
|
|
||||||
import 'get_attachment_displayed_test.mocks.dart';
|
|
||||||
|
|
||||||
@GenerateMocks([BuildContext, ResponsiveUtils])
|
|
||||||
void main() {
|
void main() {
|
||||||
late MockBuildContext mockContext;
|
List<Attachment> generateAttachments(int count) =>
|
||||||
late MockResponsiveUtils mockResponsiveUtils;
|
List.generate(count, (i) => Attachment(name: 'A$i'));
|
||||||
late List<Attachment> attachments;
|
|
||||||
|
|
||||||
setUp(() {
|
group('EmailUtils::getAttachmentDisplayed::', () {
|
||||||
mockContext = MockBuildContext();
|
test('Should returns empty list when attachments list is empty', () {
|
||||||
mockResponsiveUtils = MockResponsiveUtils();
|
expect(
|
||||||
attachments = [
|
EmailUtils.getAttachmentDisplayed(
|
||||||
Attachment(name: 'file1.pdf'),
|
maxWidth: 1000,
|
||||||
Attachment(name: 'file2.jpg'),
|
attachments: [],
|
||||||
Attachment(name: 'file3.png'),
|
isMobile: true,
|
||||||
];
|
),
|
||||||
|
[]);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('on mobile devices', () {
|
||||||
|
test('Should returns all attachments when there are 3 or fewer', () {
|
||||||
|
final attachments = generateAttachments(2);
|
||||||
|
final result = EmailUtils.getAttachmentDisplayed(
|
||||||
|
maxWidth: 1000,
|
||||||
|
attachments: attachments,
|
||||||
|
isMobile: true,
|
||||||
|
);
|
||||||
|
expect(result, attachments);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should returns first 3 attachments when more than 3 exist', () {
|
||||||
|
final attachments = generateAttachments(5);
|
||||||
|
final result = EmailUtils.getAttachmentDisplayed(
|
||||||
|
maxWidth: 1000,
|
||||||
|
attachments: attachments,
|
||||||
|
isMobile: true,
|
||||||
|
);
|
||||||
|
expect(result, attachments.sublist(0, 3));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('on non-mobile (desktop/web)', () {
|
||||||
|
test('Should returns all attachments if maxWidth can fit all items', () {
|
||||||
|
final attachments = generateAttachments(2);
|
||||||
|
final result = EmailUtils.getAttachmentDisplayed(
|
||||||
|
maxWidth: 700,
|
||||||
|
attachments: attachments,
|
||||||
|
isMobile: false,
|
||||||
|
);
|
||||||
|
expect(result, attachments);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should returns only the number of items that fit in maxWidth', () {
|
||||||
|
final attachments = generateAttachments(5);
|
||||||
|
final result = EmailUtils.getAttachmentDisplayed(
|
||||||
|
maxWidth: 900,
|
||||||
|
attachments: attachments,
|
||||||
|
isMobile: false,
|
||||||
|
);
|
||||||
|
expect(result, attachments.sublist(0, 3));
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'Should returns only the first attachment if maxWidth is too small for any',
|
||||||
|
() {
|
||||||
|
final attachments = generateAttachments(3);
|
||||||
|
final result = EmailUtils.getAttachmentDisplayed(
|
||||||
|
maxWidth: 100,
|
||||||
|
attachments: attachments,
|
||||||
|
isMobile: false,
|
||||||
|
);
|
||||||
|
expect(result, [attachments.first]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'Should clamps the number of displayed attachments to the list length',
|
||||||
|
() {
|
||||||
|
final attachments = generateAttachments(2);
|
||||||
|
final result = EmailUtils.getAttachmentDisplayed(
|
||||||
|
maxWidth: 2000,
|
||||||
|
attachments: attachments,
|
||||||
|
isMobile: false,
|
||||||
|
);
|
||||||
|
expect(result, attachments);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
test('should return empty list when attachments are empty', () {
|
|
||||||
final result = EmailUtils.getAttachmentDisplayed(
|
|
||||||
context: mockContext,
|
|
||||||
responsiveUtils: mockResponsiveUtils,
|
|
||||||
maxWidth: 300.0,
|
|
||||||
platformIsMobile: true,
|
|
||||||
attachments: [],
|
|
||||||
);
|
|
||||||
expect(result, []);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should return all attachments when mobile and attachments < 3', () {
|
|
||||||
when(mockResponsiveUtils.isMobile(mockContext)).thenReturn(true);
|
|
||||||
|
|
||||||
final result = EmailUtils.getAttachmentDisplayed(
|
|
||||||
context: mockContext,
|
|
||||||
responsiveUtils: mockResponsiveUtils,
|
|
||||||
maxWidth: 300.0,
|
|
||||||
platformIsMobile: true,
|
|
||||||
attachments: attachments.sublist(0, 2),
|
|
||||||
);
|
|
||||||
expect(result.length, 2);
|
|
||||||
expect(result, attachments.sublist(0, 2));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should return first 3 attachments when mobile and attachments >= 4', () {
|
|
||||||
when(mockResponsiveUtils.isMobile(mockContext)).thenReturn(true);
|
|
||||||
|
|
||||||
final result = EmailUtils.getAttachmentDisplayed(
|
|
||||||
context: mockContext,
|
|
||||||
responsiveUtils: mockResponsiveUtils,
|
|
||||||
maxWidth: 300.0,
|
|
||||||
platformIsMobile: true,
|
|
||||||
attachments: attachments,
|
|
||||||
);
|
|
||||||
expect(result.length, 3);
|
|
||||||
expect(result, attachments.sublist(0, 3));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should return sublist based on maxWidthTabletLarge when responsiveIsTabletLarge is true', () {
|
|
||||||
when(mockResponsiveUtils.isMobile(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isTablet(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isTabletLarge(mockContext)).thenReturn(true);
|
|
||||||
final result = EmailUtils.getAttachmentDisplayed(
|
|
||||||
context: mockContext,
|
|
||||||
responsiveUtils: mockResponsiveUtils,
|
|
||||||
maxWidth: 360.0,
|
|
||||||
platformIsMobile: false,
|
|
||||||
attachments: attachments,
|
|
||||||
);
|
|
||||||
expect(result.length, 1);
|
|
||||||
expect(result, attachments.sublist(0, 1));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should return sublist based on maxWidthTablet when responsiveIsTablet is true', () {
|
|
||||||
when(mockResponsiveUtils.isMobile(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isTablet(mockContext)).thenReturn(true);
|
|
||||||
when(mockResponsiveUtils.isTabletLarge(mockContext)).thenReturn(false);
|
|
||||||
|
|
||||||
final result = EmailUtils.getAttachmentDisplayed(
|
|
||||||
context: mockContext,
|
|
||||||
responsiveUtils: mockResponsiveUtils,
|
|
||||||
maxWidth: 320.0,
|
|
||||||
platformIsMobile: false,
|
|
||||||
attachments: attachments,
|
|
||||||
);
|
|
||||||
expect(result.length, 1);
|
|
||||||
expect(result, attachments.sublist(0, 1));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should return sublist based on maxWidthMobile when not tablet or tabletLarge', () {
|
|
||||||
when(mockResponsiveUtils.isMobile(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isTablet(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isTabletLarge(mockContext)).thenReturn(false);
|
|
||||||
|
|
||||||
final result = EmailUtils.getAttachmentDisplayed(
|
|
||||||
context: mockContext,
|
|
||||||
responsiveUtils: mockResponsiveUtils,
|
|
||||||
maxWidth: 280.0,
|
|
||||||
platformIsMobile: false,
|
|
||||||
attachments: attachments,
|
|
||||||
);
|
|
||||||
expect(result.length, 1);
|
|
||||||
expect(result, attachments.sublist(0, 1));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should return sublist based on maxWidthMobile when platformIsMobile and responsiveIsMobile are true', () {
|
|
||||||
when(mockResponsiveUtils.isTablet(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isTabletLarge(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isMobile(mockContext)).thenReturn(true);
|
|
||||||
|
|
||||||
final result = EmailUtils.getAttachmentDisplayed(
|
|
||||||
context: mockContext,
|
|
||||||
responsiveUtils: mockResponsiveUtils,
|
|
||||||
maxWidth: 280.0,
|
|
||||||
platformIsMobile: true,
|
|
||||||
attachments: attachments,
|
|
||||||
);
|
|
||||||
expect(result.length, 3);
|
|
||||||
expect(result, attachments.sublist(0, 3));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should return sublist based on maxWidthTablet when platformIsMobile is true and responsiveIsMobile is false', () {
|
|
||||||
when(mockResponsiveUtils.isMobile(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isTablet(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isTabletLarge(mockContext)).thenReturn(false);
|
|
||||||
|
|
||||||
final result = EmailUtils.getAttachmentDisplayed(
|
|
||||||
context: mockContext,
|
|
||||||
responsiveUtils: mockResponsiveUtils,
|
|
||||||
maxWidth: 320.0,
|
|
||||||
platformIsMobile: true,
|
|
||||||
attachments: attachments,
|
|
||||||
);
|
|
||||||
expect(result.length, 1);
|
|
||||||
expect(result, attachments.sublist(0, 1));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should return first attachment when possibleDisplayedCount is 0', () {
|
|
||||||
when(mockResponsiveUtils.isMobile(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isTablet(mockContext)).thenReturn(false);
|
|
||||||
when(mockResponsiveUtils.isTabletLarge(mockContext)).thenReturn(false);
|
|
||||||
|
|
||||||
final result = EmailUtils.getAttachmentDisplayed(
|
|
||||||
context: mockContext,
|
|
||||||
responsiveUtils: mockResponsiveUtils,
|
|
||||||
maxWidth: 100.0,
|
|
||||||
platformIsMobile: false,
|
|
||||||
attachments: attachments,
|
|
||||||
);
|
|
||||||
expect(result.length, 1);
|
|
||||||
expect(result.first, attachments.first);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user