TF-295 Apply new UI for composer mobile

This commit is contained in:
dab246
2022-03-16 18:05:40 +07:00
committed by Dat H. Pham
parent 1f9fd7c0a7
commit c751cabd06
7 changed files with 292 additions and 263 deletions
+6
View File
@@ -0,0 +1,6 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="18" fill="#007AFF" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M20.7351 10.3422C20.5546 10.133 20.291 10 19.9948 10C19.6862 10 19.4132 10.1449 19.2327 10.3696C19.1941 10.4179 12.3893 17.225 12.3893 17.225C12.003 17.614 12.003 18.3302 12.3893 18.7188C12.7755 19.1078 13.5678 19.1078 13.9535 18.7188L18.8633 13.7378V28.7207C18.8633 29.2736 19.4488 29.7 19.9948 29.7C20.5413 29.7 21.1561 29.2736 21.1561 28.7207V13.7378L26.109 18.8763C26.4947 19.2653 27.2237 19.2653 27.6099 18.8763C27.9962 18.4878 27.9962 17.614 27.6099 17.225C27.6099 17.225 20.7722 10.385 20.7351 10.3422Z"
fill="white" />
</svg>

After

Width:  |  Height:  |  Size: 752 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="18" fill="#3C3C43" fill-opacity="0.18"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.7355 10.3422C20.555 10.133 20.2914 10 19.9951 10C19.6865 10 19.4135 10.1449 19.233 10.3696C19.1945 10.4179 12.3897 17.225 12.3897 17.225C12.0034 17.614 12.0034 18.3302 12.3897 18.7188C12.7759 19.1078 13.5681 19.1078 13.9539 18.7188L18.8637 13.7378V28.7207C18.8637 29.2736 19.4492 29.7 19.9951 29.7C20.5416 29.7 21.1565 29.2736 21.1565 28.7207V13.7378L26.1093 18.8763C26.4951 19.2653 27.224 19.2653 27.6103 18.8763C27.9965 18.4878 27.9965 17.614 27.6103 17.225C27.6103 17.225 20.7726 10.385 20.7355 10.3422Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 747 B

@@ -73,6 +73,8 @@ class ImagePaths {
String get icDeleteComposer => _getImagePath('ic_delete_composer.svg');
String get icFileAttachment => _getImagePath('ic_file_attachment.svg');
String get icDeleteAttachment => _getImagePath('ic_delete_attachment.svg');
String get icSendMobile => _getImagePath('ic_send_mobile.svg');
String get icSendMobileDisable => _getImagePath('ic_send_mobile_disable.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
@@ -54,6 +54,7 @@ class ComposerController extends BaseController {
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
final expandMode = ExpandMode.COLLAPSE.obs;
final expandModeMobile = ExpandMode.EXPAND.obs;
final expandModeAttachments = ExpandMode.EXPAND.obs;
final composerArguments = Rxn<ComposerArguments>();
final isEnableEmailSendButton = false.obs;
@@ -709,8 +710,11 @@ class ComposerController extends BaseController {
}
}
void backToEmailViewAction(BuildContext context) {
clearFocusEditor(context);
void collapseComposer(ExpandMode expandMode) {
expandModeMobile.value = expandMode;
}
void closeComposer(BuildContext context) {
popBack();
}
}
@@ -1,17 +1,17 @@
import 'package:core/core.dart';
import 'package:enough_html_editor/enough_html_editor.dart';
import 'package:file_picker/file_picker.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:html_editor_enhanced/html_editor.dart' as HtmlEditorBrowser;
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_file_composer_builder.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/top_bar_composer_widget_builder.dart';
import 'package:tmail_ui_user/features/email/presentation/widgets/attachment_file_tile_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class ComposerView extends GetWidget<ComposerController> {
@@ -38,16 +38,17 @@ class ComposerView extends GetWidget<ComposerController> {
right: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
left: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
child: Container(
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
alignment: Alignment.topCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
_buildTopBar(context),
Expanded(child: _buildBodyComposer(context))
color: Colors.white,
child: Column(children: [
Obx(() => Padding(
padding: EdgeInsets.only(left: 8, right: 8,
top: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context) ? 16 : 0,
bottom: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context) ? 8 : 0),
child: _buildAppBar(context, controller.isEnableEmailSendButton.value, controller.expandModeMobile.value),)),
Obx(() => controller.expandModeMobile == ExpandMode.COLLAPSE
? Divider(color: AppColor.colorDividerComposer, height: 1)
: SizedBox.shrink()),
Expanded(child: _buildEditorAndAttachments(context))
])
)
),
@@ -56,26 +57,58 @@ class ComposerView extends GetWidget<ComposerController> {
);
}
Widget _buildTopBar(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
child: Obx(() => (TopBarComposerWidgetBuilder(context, imagePaths, controller.isEnableEmailSendButton.value)
..addSendEmailActionClick(() {
controller.sendEmailAction(context);
})
..addAttachFileActionClick((position) {
if (kIsWeb) {
controller.openPickAttachmentsForWeb(context,position, _pickAttachmentsActionTilesForWeb(context));
} else {
controller.openPickAttachmentMenu(context, _pickAttachmentsActionTiles(context));
}
})
..addBackActionClick(() {
controller.saveEmailAsDrafts(context);
controller.backToEmailViewAction(context);
}))
.build()),
);
Widget _buildAppBar(BuildContext context, bool isEnableSendButton, ExpandMode expandModeMobile) {
return Row(children: [
Material(
type: MaterialType.circle,
color: Colors.transparent,
child: TextButton(
child: Text(
AppLocalizations.of(context).cancel,
style: TextStyle(fontWeight: FontWeight.normal, fontSize: 17, color: AppColor.colorTextButton)),
onPressed: () {
controller.saveEmailAsDrafts(context);
controller.closeComposer(context);
}
)
),
if (expandModeMobile == ExpandMode.EXPAND)
Spacer(),
if (expandModeMobile == ExpandMode.COLLAPSE)
Expanded(child: Text(
AppLocalizations.of(context).new_message.capitalizeFirstEach,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
maxLines: 1,
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w600, color: Colors.black),
)),
buildIconWeb(
icon: SvgPicture.asset(imagePaths.icAttachmentsComposer, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).pick_attachments,
onTap: () => controller.openPickAttachmentMenu(context, _pickAttachmentsActionTiles(context))),
if (expandModeMobile == ExpandMode.COLLAPSE)
buildIconWeb(
icon: SvgPicture.asset(isEnableSendButton ? imagePaths.icSendMobile : imagePaths.icSendMobileDisable, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).send,
onTap: () => controller.sendEmailAction(context)),
]);
}
Widget _buildTitleComposer(BuildContext context, bool isEnableSendButton) {
return Row(children: [
Expanded(child: Text(
AppLocalizations.of(context).new_message.capitalizeFirstEach,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(fontSize: 34, fontWeight: FontWeight.w700, color: Colors.black),
)),
buildIconWeb(
iconSize: 36,
iconPadding: EdgeInsets.zero,
icon: SvgPicture.asset(isEnableSendButton ? imagePaths.icSendMobile : imagePaths.icSendMobileDisable, width: 36, height: 36, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).send,
onTap: () => controller.sendEmailAction(context)),
]);
}
List<Widget> _pickAttachmentsActionTiles(BuildContext context) {
@@ -86,14 +119,6 @@ class ComposerView extends GetWidget<ComposerController> {
];
}
List<PopupMenuEntry> _pickAttachmentsActionTilesForWeb(BuildContext context) {
return [
PopupMenuItem(padding: EdgeInsets.symmetric(horizontal: 8), child: _pickPhotoAndVideoAction(context)),
PopupMenuDivider(height: 0.5),
PopupMenuItem(padding: EdgeInsets.symmetric(horizontal: 8), child: _browseFileAction(context)),
];
}
Widget _pickPhotoAndVideoAction(BuildContext context) {
return (SimpleContextMenuActionBuilder(
Key('pick_photo_and_video_context_menu_action'),
@@ -112,251 +137,238 @@ class ComposerView extends GetWidget<ComposerController> {
.build();
}
Widget _buildEmailHeader(BuildContext context) {
return Container(
margin: EdgeInsets.zero,
padding: EdgeInsets.only(top: 20),
color: Colors.white,
alignment: Alignment.topCenter,
child: Column(
children: [
Padding(
padding: EdgeInsets.only(left: 16),
child: _buildEmailAddress(context)),
_buildDivider(),
_buildSubjectEmail(context),
_buildDivider(),
],
),
);
}
Widget _buildDivider(){
return Padding(
padding: EdgeInsets.only(left: 16),
child: Divider(color: AppColor.colorDividerComposer, height: 1));
}
Widget _buildEmailAddress(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(bottom: 12),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(right: 8),
child: Text(
'${AppLocalizations.of(context).from_email_address_prefix}:',
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Obx(() => controller.composerArguments.value != null
? Text(
'<${controller.getEmailAddressSender()}>',
style: TextStyle(fontSize: 14, color: AppColor.colorEmailAddress, fontWeight: FontWeight.w500))
: SizedBox.shrink()
)
],
)
)
]
)
),
Divider(color: AppColor.colorDividerComposer, height: 1),
Obx(() => (EmailAddressInputBuilder(
return Column(children: [
Obx(() => (EmailAddressInputBuilder(
context,
imagePaths,
_appToast,
PrefixEmailAddress.to,
controller.listToEmailAddress,
controller: controller.toEmailAddressController,
isInitial: controller.isInitialRecipient.value,
expandMode: controller.expandMode.value)
..addExpandAddressActionClick(() => controller.expandEmailAddressAction())
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
.build()
),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? Divider(color: AppColor.colorDividerComposer, height: 1)
: SizedBox.shrink()),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? (EmailAddressInputBuilder(
context,
imagePaths,
_appToast,
PrefixEmailAddress.to,
controller.listToEmailAddress,
controller: controller.toEmailAddressController,
isInitial: controller.isInitialRecipient.value,
expandMode: controller.expandMode.value)
..addExpandAddressActionClick(() => controller.expandEmailAddressAction())
PrefixEmailAddress.cc,
controller.listCcEmailAddress,
controller: controller.ccEmailAddressController,
isInitial: controller.isInitialRecipient.value,)
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
.build()
),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? Divider(color: AppColor.colorDividerComposer, height: 1)
: SizedBox.shrink()),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? (EmailAddressInputBuilder(
context,
imagePaths,
_appToast,
PrefixEmailAddress.cc,
controller.listCcEmailAddress,
controller: controller.ccEmailAddressController,
isInitial: controller.isInitialRecipient.value,)
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
.build()
: SizedBox.shrink()
),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? Divider(color: AppColor.colorDividerComposer, height: 1)
: SizedBox.shrink()),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? (EmailAddressInputBuilder(
context,
imagePaths,
_appToast,
PrefixEmailAddress.bcc,
controller.listBccEmailAddress,
controller: controller.bccEmailAddressController,
isInitial: controller.isInitialRecipient.value,)
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
.build()
: SizedBox.shrink()
),
],
);
: SizedBox.shrink()
),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? Divider(color: AppColor.colorDividerComposer, height: 1)
: SizedBox.shrink()),
Obx(() => controller.expandMode.value == ExpandMode.EXPAND
? (EmailAddressInputBuilder(
context,
imagePaths,
_appToast,
PrefixEmailAddress.bcc,
controller.listBccEmailAddress,
controller: controller.bccEmailAddressController,
isInitial: controller.isInitialRecipient.value,)
..addOnUpdateListEmailAddressAction((prefixEmailAddress, listEmailAddress) => controller.updateListEmailAddress(prefixEmailAddress, listEmailAddress))
..addOnSuggestionEmailAddress((word) => controller.getAutoCompleteSuggestion(word)))
.build()
: SizedBox.shrink()
),
]);
}
Widget _buildSubjectEmail(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(right: 8),
child: Text(
'${AppLocalizations.of(context).subject_email}:',
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))),
Expanded(
child: (TextFieldBuilder()
..key(Key('subject_email_input'))
..textInputAction(TextInputAction.newline)
..maxLines(null)
..cursorColor(AppColor.colorTextButton)
..onChange((value) => controller.setSubjectEmail(value))
..textStyle(TextStyle(color: AppColor.colorEmailAddress, fontSize: 15))
..textDecoration(InputDecoration(
contentPadding: EdgeInsets.zero,
border: InputBorder.none))
..addController(controller.subjectEmailInputController))
.build()
)
]
)
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(right: 8, top: 16),
child: Text(
'${AppLocalizations.of(context).subject_email}:',
style: TextStyle(fontSize: 15, color: AppColor.colorHintEmailAddressInput))),
Expanded(
child: (TextFieldBuilder()
..key(Key('subject_email_input'))
..cursorColor(AppColor.colorTextButton)
..onChange((value) => controller.setSubjectEmail(value))
..textStyle(TextStyle(color: AppColor.colorEmailAddress, fontSize: 15))
..textDecoration(InputDecoration(contentPadding: EdgeInsets.zero, border: InputBorder.none))
..addController(controller.subjectEmailInputController))
.build()
)
]
);
}
Widget _buildBodyComposer(BuildContext context) {
return SingleChildScrollView(
physics: ClampingScrollPhysics(),
child: Column(
children: [
_buildEmailHeader(context),
Container(
color: Colors.white,
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
alignment: Alignment.topCenter,
child: Column(
children: [
if (kIsWeb) _buildAttachmentsLoadingView(),
Padding(
padding: EdgeInsets.only(top: 8, left: 16, right: 16, bottom: 24),
child: _buildComposerEditor(context)),
if (!kIsWeb) _buildAttachmentsLoadingView(),
_buildAttachments(context),
],
),
)
]
)
Widget _buildEditorAndAttachments(BuildContext context) {
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollInfo) {
if (scrollInfo is ScrollEndNotification) {
if (scrollInfo.metrics.pixels >= 30) {
controller.collapseComposer(ExpandMode.COLLAPSE);
} else if (scrollInfo.metrics.pixels <= scrollInfo.metrics.minScrollExtent) {
controller.collapseComposer(ExpandMode.EXPAND);
}
}
return false;
},
child: SingleChildScrollView(
physics: ClampingScrollPhysics(),
child: Column(children: [
Obx(() => Padding(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: _buildTitleComposer(context, controller.isEnableEmailSendButton.value))),
Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: _buildEmailAddress(context)),
Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: _buildSubjectEmail(context)),
Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: Divider(color: AppColor.colorDividerComposer, height: 1)),
Obx(() => controller.attachments.isNotEmpty
? Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: _buildAttachmentsTitle(context, controller.attachments, controller.expandModeAttachments.value))
: SizedBox.shrink()),
Obx(() => controller.attachments.isEmpty
? _buildAttachmentsLoadingView()
: SizedBox.shrink()),
Obx(() => controller.attachments.isNotEmpty
? Padding(
padding: EdgeInsets.only(bottom: 8, left: 16, right: 16),
child: _buildAttachmentsList(context, controller.attachments, controller.expandModeAttachments.value))
: SizedBox.shrink()),
Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: _buildComposerEditor(context)),
])
)
);
}
Widget _buildComposerEditor(BuildContext context) {
return Obx(() {
if (kIsWeb) {
return HtmlEditorBrowser.HtmlEditor(
if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) {
return HtmlEditor(
key: Key('composer_editor'),
controller: controller.htmlControllerBrowser,
htmlEditorOptions: HtmlEditorBrowser.HtmlEditorOptions(
shouldEnsureVisible: true,
hint: '',
initialText: controller.getContentEmail(),
autoAdjustHeight: controller.getContentEmail().isNotEmpty,
),
htmlToolbarOptions: HtmlEditorBrowser.HtmlToolbarOptions(
toolbarPosition: HtmlEditorBrowser.ToolbarPosition.custom
),
otherOptions: HtmlEditorBrowser.OtherOptions(height: 400),
);
minHeight: 550,
onCreated: (editorApi) => controller.htmlEditorApi = editorApi);
} else {
if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) {
return HtmlEditor(
key: Key('composer_editor'),
minHeight: 100,
onCreated: (editorApi) => controller.htmlEditorApi = editorApi);
} else {
final message = controller.getContentEmail();
return message.isNotEmpty
? HtmlEditor(
key: Key('composer_editor'),
minHeight: 100,
onCreated: (editorApi) => controller.htmlEditorApi = editorApi,
initialContent: message)
: SizedBox.shrink();
}
final message = controller.getContentEmail();
return message.isNotEmpty
? HtmlEditor(
key: Key('composer_editor'),
minHeight: 550,
onCreated: (editorApi) => controller.htmlEditorApi = editorApi,
initialContent: message)
: SizedBox.shrink();
}
});
}
Widget _buildAttachmentsLoadingView() {
Widget _buildAttachmentsLoadingView({EdgeInsets? padding, double? size}) {
return Obx(() => controller.viewState.value.fold(
(failure) => SizedBox.shrink(),
(success) => success is UploadingAttachmentState
? Center(child: Padding(
padding: EdgeInsets.only(bottom: controller.attachments.isNotEmpty ? 0 : 24, top: kIsWeb ? 20 : 0),
? Center(child: Padding(
padding: padding ?? EdgeInsets.all(10),
child: SizedBox(
width: size ?? 20,
height: size ?? 20,
child: CupertinoActivityIndicator(color: AppColor.colorTextButton))))
: SizedBox.shrink()));
}
Widget _buildAttachmentsTitle(BuildContext context, List<Attachment> attachments, ExpandMode expandModeAttachment) {
return Row(
children: [
Text(
'${AppLocalizations.of(context).attachments} (${filesize(attachments.totalSize(), 0)}):',
style: TextStyle(fontSize: 12, color: AppColor.colorHintEmailAddressInput, fontWeight: FontWeight.normal)),
_buildAttachmentsLoadingView(padding: EdgeInsets.only(left: 16), size: 16),
Spacer(),
Material(
type: MaterialType.circle,
color: Colors.transparent,
child: TextButton(
child: Text(
expandModeAttachment == ExpandMode.EXPAND
? AppLocalizations.of(context).hide
: '${AppLocalizations.of(context).show_all} (${attachments.length})',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 12, color: AppColor.colorTextButton)),
onPressed: () => controller.toggleDisplayAttachments()
)
)
],
);
}
Widget _buildAttachmentsList(BuildContext context, List<Attachment> attachments, ExpandMode expandMode) {
if (expandMode == ExpandMode.EXPAND) {
return LayoutBuilder(builder: (context, constraints) {
return GridView.builder(
key: Key('list_attachment_full'),
primary: false,
shrinkWrap: true,
itemCount: attachments.length,
gridDelegate: SliverGridDelegateFixedHeight(
height: 60,
crossAxisCount: _getMaxItemRowListAttachment(context, constraints),
crossAxisSpacing: 8.0,
mainAxisSpacing: 8.0),
itemBuilder: (context, index) =>
(AttachmentFileComposerBuilder(context, imagePaths, attachments[index])
..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment)))
.build()
);
});
} else {
return LayoutBuilder(builder: (context, constraints) {
return Align(
alignment: Alignment.centerLeft,
child: SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(color: AppColor.primaryColor))))
: SizedBox.shrink()));
height: 60,
child: ListView.builder(
key: Key('list_attachment_minimize'),
shrinkWrap: true,
physics: ClampingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: attachments.length,
itemBuilder: (context, index) =>
(AttachmentFileComposerBuilder(context, imagePaths, attachments[index],
itemMargin: EdgeInsets.only(right: 8),
maxWidth: _getMaxWidthItemListAttachment(context, constraints),
maxHeight: 60)
..addOnDeleteAttachmentAction((attachment) => controller.removeAttachmentAction(attachment)))
.build()
)
)
);
});
}
}
Widget _buildAttachments(BuildContext context) {
return Obx(() => controller.attachments.isNotEmpty
? ListView.builder(
shrinkWrap: true,
primary: false,
key: Key('attachment_list'),
padding: EdgeInsets.only(top: 16, bottom: 24, right: 50, left: 24),
itemCount: controller.attachments.length,
itemBuilder: (context, index) => (AttachmentFileTileBuilder(
imagePaths,
controller.attachments[index],
0,
0)
..height(60)
..addButtonAction(_buildRemoveButtonAttachment(controller.attachments[index])))
.build())
: SizedBox.shrink());
int _getMaxItemRowListAttachment(BuildContext context, BoxConstraints constraints) {
if (constraints.maxWidth < ResponsiveUtils.minTabletWidth) {
return 2;
} else if (constraints.maxWidth < ResponsiveUtils.minTabletLargeWidth) {
return 3;
} else {
return 4;
}
}
Widget _buildRemoveButtonAttachment(Attachment attachment) {
return (IconBuilder(imagePaths.icComposerClose)
..size(35)
..addOnTapActionClick(() => controller.removeAttachmentAction(attachment)))
.build();
double _getMaxWidthItemListAttachment(BuildContext context, BoxConstraints constraints) {
return constraints.maxWidth / _getMaxItemRowListAttachment(context, constraints);
}
}
@@ -1,6 +1,7 @@
import 'package:core/core.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:model/model.dart';
@@ -53,13 +54,13 @@ class AttachmentFileComposerBuilder {
color: Colors.white),
child: Stack(children: [
ListTile(
contentPadding: EdgeInsets.only(right: 16),
contentPadding: EdgeInsets.only(right: kIsWeb ? 16 : 18),
onTap: () {},
leading: Transform(
transform: Matrix4.translationValues(8.0, -3.0, 0.0),
transform: Matrix4.translationValues(8.0, kIsWeb ? -3.0 : -5.0, 0.0),
child: SvgPicture.asset(imagePaths.icFileAttachment, fit: BoxFit.fill)),
title: Transform(
transform: Matrix4.translationValues(-4.0, -6.0, 0.0),
transform: Matrix4.translationValues(kIsWeb ? -4.0 : -10.0, kIsWeb ? -6.0 : -9.0, 0.0),
child: Text(
attachment.name ?? '',
maxLines: 2,
@@ -68,7 +69,7 @@ class AttachmentFileComposerBuilder {
)),
subtitle: attachment.size != null && attachment.size?.value != 0
? Transform(
transform: Matrix4.translationValues(-4.0, -5.0, 0.0),
transform: Matrix4.translationValues(kIsWeb ? -4.0 : -10.0, kIsWeb ? -5.0 : -8.0, 0.0),
child: Text(
filesize(attachment.size?.value, 0),
maxLines: 1,
@@ -76,7 +77,7 @@ class AttachmentFileComposerBuilder {
style: TextStyle(fontSize: 10, color: AppColor.colorContentEmail, fontWeight: FontWeight.normal)))
: null,
),
Positioned(right: -5, top: -5, child: buildIconWeb(
Positioned(right: kIsWeb ? -5 : -12, top: kIsWeb ? -5 : -12, child: buildIconWeb(
icon: SvgPicture.asset(imagePaths.icDeleteAttachment, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).delete,
onTap: () => _onDeleteAttachmentAction?.call(attachment)))
@@ -71,7 +71,7 @@ class EmailAddressInputBuilder {
Expanded(child: _buildTagEditor()),
if (_prefixEmailAddress == PrefixEmailAddress.to)
Padding(
padding: EdgeInsets.only(top: 8),
padding: EdgeInsets.only(top: kIsWeb ? 8 : 0),
child: _buildButtonExpandAddress())
]
);