From c751cabd06c37948dfa1112bc81fa10e17bc8f1f Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 16 Mar 2022 18:05:40 +0700 Subject: [PATCH] TF-295 Apply new UI for composer mobile --- assets/images/ic_send_mobile.svg | 6 + assets/images/ic_send_mobile_disable.svg | 4 + .../presentation/resources/image_paths.dart | 2 + .../presentation/composer_controller.dart | 8 +- .../composer/presentation/composer_view.dart | 522 +++++++++--------- .../attachment_file_composer_builder.dart | 11 +- .../widgets/email_address_input_builder.dart | 2 +- 7 files changed, 292 insertions(+), 263 deletions(-) create mode 100644 assets/images/ic_send_mobile.svg create mode 100644 assets/images/ic_send_mobile_disable.svg diff --git a/assets/images/ic_send_mobile.svg b/assets/images/ic_send_mobile.svg new file mode 100644 index 000000000..b40f23286 --- /dev/null +++ b/assets/images/ic_send_mobile.svg @@ -0,0 +1,6 @@ + + + + diff --git a/assets/images/ic_send_mobile_disable.svg b/assets/images/ic_send_mobile_disable.svg new file mode 100644 index 000000000..64f85c188 --- /dev/null +++ b/assets/images/ic_send_mobile_disable.svg @@ -0,0 +1,4 @@ + + + + diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart index fa43be498..100ed9672 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -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; diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 82f179931..6f3626a1b 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -54,6 +54,7 @@ class ComposerController extends BaseController { final mailboxDashBoardController = Get.find(); final expandMode = ExpandMode.COLLAPSE.obs; + final expandModeMobile = ExpandMode.EXPAND.obs; final expandModeAttachments = ExpandMode.EXPAND.obs; final composerArguments = Rxn(); 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(); } } \ No newline at end of file diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index 3c20928e8..8e1daf959 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -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 { @@ -38,16 +38,17 @@ class ComposerView extends GetWidget { 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 { ); } - 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 _pickAttachmentsActionTiles(BuildContext context) { @@ -86,14 +119,6 @@ class ComposerView extends GetWidget { ]; } - List _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 { .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( + 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 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 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); } } \ No newline at end of file diff --git a/lib/features/composer/presentation/widgets/attachment_file_composer_builder.dart b/lib/features/composer/presentation/widgets/attachment_file_composer_builder.dart index 671cacc2f..8e9146fa2 100644 --- a/lib/features/composer/presentation/widgets/attachment_file_composer_builder.dart +++ b/lib/features/composer/presentation/widgets/attachment_file_composer_builder.dart @@ -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))) diff --git a/lib/features/composer/presentation/widgets/email_address_input_builder.dart b/lib/features/composer/presentation/widgets/email_address_input_builder.dart index 20df7b44f..c817103fc 100644 --- a/lib/features/composer/presentation/widgets/email_address_input_builder.dart +++ b/lib/features/composer/presentation/widgets/email_address_input_builder.dart @@ -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()) ] );