From 27b5342132d063db613235b2050257b77d31e7a1 Mon Sep 17 00:00:00 2001 From: dab246 Date: Thu, 7 Sep 2023 22:49:26 +0700 Subject: [PATCH] TF-2116 Apply new design attachment in mobile composer (cherry picked from commit 4d8a7590e11044963093a98095948d9820f34efb) --- .../styles/circle_loading_widget_styles.dart | 8 + .../base/styles/popup_item_widget_style.dart | 3 +- .../base/widget/circle_loading_widget.dart | 36 +++ .../base/widget/popup_item_widget.dart | 1 + .../composer/presentation/composer_view.dart | 21 +- .../presentation/composer_view_web.dart | 261 ++++++++++-------- .../presentation/styles/composer_style.dart | 1 + ...bile_attachment_composer_widget_style.dart | 13 +- .../view/mobile/mobile_container_view.dart | 10 +- .../attachment_item_composer_widget.dart | 1 + .../insert_image_loading_bar_widget.dart | 55 ++++ .../mobile_attachment_composer_widget.dart | 105 ++++--- .../email/presentation/email_view.dart | 3 +- .../email_view_loading_bar_widget.dart | 3 - 14 files changed, 327 insertions(+), 194 deletions(-) create mode 100644 lib/features/base/styles/circle_loading_widget_styles.dart create mode 100644 lib/features/base/widget/circle_loading_widget.dart create mode 100644 lib/features/composer/presentation/widgets/insert_image_loading_bar_widget.dart diff --git a/lib/features/base/styles/circle_loading_widget_styles.dart b/lib/features/base/styles/circle_loading_widget_styles.dart new file mode 100644 index 000000000..f8544f381 --- /dev/null +++ b/lib/features/base/styles/circle_loading_widget_styles.dart @@ -0,0 +1,8 @@ +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:flutter/material.dart'; + +class CircleLoadingWidgetStyles { + static const Color progressColor = AppColor.primaryColor; + static const double size = 24; + static const double width = 2; +} \ No newline at end of file diff --git a/lib/features/base/styles/popup_item_widget_style.dart b/lib/features/base/styles/popup_item_widget_style.dart index 8aac934af..b7317eecb 100644 --- a/lib/features/base/styles/popup_item_widget_style.dart +++ b/lib/features/base/styles/popup_item_widget_style.dart @@ -1,10 +1,11 @@ import 'package:flutter/material.dart'; class PopupItemWidgetStyle { - static const double iconSize = 20; + static const double iconSize = 24; static const double selectedIconSize = 16; static const double space = 12; static const double height = 48; + static const double minWidth = 256; static const EdgeInsetsGeometry padding = EdgeInsets.symmetric(horizontal: 20, vertical: 16); static const EdgeInsetsGeometry iconSelectedPadding = EdgeInsetsDirectional.only(start: 12); diff --git a/lib/features/base/widget/circle_loading_widget.dart b/lib/features/base/widget/circle_loading_widget.dart new file mode 100644 index 000000000..5b635d184 --- /dev/null +++ b/lib/features/base/widget/circle_loading_widget.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/features/base/styles/circle_loading_widget_styles.dart'; + +class CircleLoadingWidget extends StatelessWidget { + + final double? size; + final EdgeInsetsGeometry? padding; + + const CircleLoadingWidget({super.key, this.size, this.padding}); + + @override + Widget build(BuildContext context) { + if (padding != null) { + return Padding( + padding: padding!, + child: SizedBox( + width: size ?? CircleLoadingWidgetStyles.size, + height: size ?? CircleLoadingWidgetStyles.size, + child: const CircularProgressIndicator( + color: CircleLoadingWidgetStyles.progressColor, + strokeWidth: CircleLoadingWidgetStyles.width, + ) + ), + ); + } else { + return SizedBox( + width: size ?? CircleLoadingWidgetStyles.size, + height: size ?? CircleLoadingWidgetStyles.size, + child: const CircularProgressIndicator( + color: CircleLoadingWidgetStyles.progressColor, + strokeWidth: CircleLoadingWidgetStyles.width, + ) + ); + } + } +} \ No newline at end of file diff --git a/lib/features/base/widget/popup_item_widget.dart b/lib/features/base/widget/popup_item_widget.dart index 480f2c338..169f51205 100644 --- a/lib/features/base/widget/popup_item_widget.dart +++ b/lib/features/base/widget/popup_item_widget.dart @@ -38,6 +38,7 @@ class PopupItemWidget extends StatelessWidget { onTap: onCallbackAction, child: Container( height: PopupItemWidgetStyle.height, + constraints: const BoxConstraints(minWidth: PopupItemWidgetStyle.minWidth), padding: padding, child: Row(children: [ SvgPicture.asset( diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index cc2d87f21..41a67e103 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -12,9 +12,11 @@ import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart'; import 'package:tmail_ui_user/features/composer/presentation/styles/composer_style.dart'; +import 'package:tmail_ui_user/features/composer/presentation/styles/mobile_app_bar_composer_widget_style.dart'; import 'package:tmail_ui_user/features/composer/presentation/view/mobile/mobile_container_view.dart'; import 'package:tmail_ui_user/features/composer/presentation/view/mobile/mobile_editor_view.dart'; import 'package:tmail_ui_user/features/composer/presentation/view/mobile/tablet_container_view.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/insert_image_loading_bar_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/mobile/mobile_attachment_composer_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/mobile/app_bar_composer_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/mobile/landscape_app_bar_composer_widget.dart'; @@ -49,6 +51,7 @@ class ComposerView extends GetWidget { onInsertImageAction: (constraints) => controller.isNetworkConnectionAvailable ? controller.insertImage(context, constraints.maxWidth) : null, + backgroundColor: MobileAppBarComposerWidgetStyle.backgroundColor, childBuilder: (context) => SafeArea( left: !_responsiveUtils.isLandscapeMobile(context), right: !_responsiveUtils.isLandscapeMobile(context), @@ -165,6 +168,13 @@ class ComposerView extends GetWidget { padding: ComposerStyle.mobileSubjectPadding, margin: ComposerStyle.mobileSubjectMargin, ), + Obx(() => Center( + child: InsertImageLoadingBarWidget( + uploadInlineViewState: controller.uploadController.uploadInlineViewState.value, + viewState: controller.viewState.value, + padding: ComposerStyle.insertImageLoadingBarPadding, + ), + )), Obx(() => GestureDetector( onTapDown: (_) { controller.removeFocusAllInputEditorHeader(); @@ -182,9 +192,7 @@ class ComposerView extends GetWidget { if (controller.uploadController.listUploadAttachments.isNotEmpty) { return MobileAttachmentComposerWidget( listFileUploaded: controller.uploadController.listUploadAttachments, - isShowMore: controller.isAttachmentCollapsed, onDeleteAttachmentAction: (fileState) => controller.deleteAttachmentUploaded(fileState.uploadTaskId), - onShowMoreAttachmentAction: (isShowMore) => controller.isAttachmentCollapsed = !isShowMore, ); } else { return const SizedBox.shrink(); @@ -300,6 +308,13 @@ class ComposerView extends GetWidget { padding: ComposerStyle.mobileSubjectPadding, margin: ComposerStyle.mobileSubjectMargin, ), + Obx(() => Center( + child: InsertImageLoadingBarWidget( + uploadInlineViewState: controller.uploadController.uploadInlineViewState.value, + viewState: controller.viewState.value, + padding: ComposerStyle.insertImageLoadingBarPadding, + ), + )), Obx(() => GestureDetector( onTapDown: (_) { controller.removeFocusAllInputEditorHeader(); @@ -317,9 +332,7 @@ class ComposerView extends GetWidget { if (controller.uploadController.listUploadAttachments.isNotEmpty) { return MobileAttachmentComposerWidget( listFileUploaded: controller.uploadController.listUploadAttachments, - isShowMore: controller.isAttachmentCollapsed, onDeleteAttachmentAction: (fileState) => controller.deleteAttachmentUploaded(fileState.uploadTaskId), - onShowMoreAttachmentAction: (isShowMore) => controller.isAttachmentCollapsed = !isShowMore, ); } else { return const SizedBox.shrink(); diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index a93d83215..bfc768f6a 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -13,6 +13,7 @@ import 'package:tmail_ui_user/features/composer/presentation/view/web/desktop_re import 'package:tmail_ui_user/features/composer/presentation/view/web/mobile_responsive_container_view.dart'; import 'package:tmail_ui_user/features/composer/presentation/view/web/tablet_responsive_container_view.dart'; import 'package:tmail_ui_user/features/composer/presentation/view/web/web_editor_view.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/insert_image_loading_bar_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/web/desktop_app_bar_composer_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/web/attachment_composer_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/web/bottom_bar_composer_widget.dart'; @@ -142,20 +143,32 @@ class ComposerView extends GetWidget { margin: ComposerStyle.mobileSubjectMargin, ), Obx(() => Expanded( - child: Padding( - padding: ComposerStyle.mobileEditorPadding, - child: WebEditorView( - editorController: controller.richTextWebController.editorController, - arguments: controller.composerArguments.value, - contentViewState: controller.emailContentsViewState.value, - currentWebContent: controller.textEditorWeb, - onInitial: controller.handleInitHtmlEditorWeb, - onChangeContent: controller.onChangeTextEditorWeb, - onFocus: controller.handleOnFocusHtmlEditorWeb, - onUnFocus: controller.handleOnUnFocusHtmlEditorWeb, - onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, - onEditorSettings: controller.richTextWebController.onEditorSettingsChange, - ), + child: Stack( + children: [ + Padding( + padding: ComposerStyle.mobileEditorPadding, + child: WebEditorView( + editorController: controller.richTextWebController.editorController, + arguments: controller.composerArguments.value, + contentViewState: controller.emailContentsViewState.value, + currentWebContent: controller.textEditorWeb, + onInitial: controller.handleInitHtmlEditorWeb, + onChangeContent: controller.onChangeTextEditorWeb, + onFocus: controller.handleOnFocusHtmlEditorWeb, + onUnFocus: controller.handleOnUnFocusHtmlEditorWeb, + onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, + onEditorSettings: controller.richTextWebController.onEditorSettingsChange, + ), + ), + Obx(() => Align( + alignment: AlignmentDirectional.topCenter, + child: InsertImageLoadingBarWidget( + uploadInlineViewState: controller.uploadController.uploadInlineViewState.value, + viewState: controller.viewState.value, + padding: ComposerStyle.insertImageLoadingBarPadding, + ), + )), + ], ), )), Obx(() { @@ -293,51 +306,63 @@ class ComposerView extends GetWidget { ), color: ComposerStyle.backgroundEditorColor ), - child: Column( + child: Stack( children: [ - Obx(() => Expanded( - child: Padding( - padding: ComposerStyle.desktopEditorPadding, - child: WebEditorView( - editorController: controller.richTextWebController.editorController, - arguments: controller.composerArguments.value, - contentViewState: controller.emailContentsViewState.value, - currentWebContent: controller.textEditorWeb, - onInitial: controller.handleInitHtmlEditorWeb, - onChangeContent: controller.onChangeTextEditorWeb, - onFocus: controller.handleOnFocusHtmlEditorWeb, - onUnFocus: controller.handleOnUnFocusHtmlEditorWeb, - onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, - onEditorSettings: controller.richTextWebController.onEditorSettingsChange, - ), + Column( + children: [ + Obx(() => Expanded( + child: Padding( + padding: ComposerStyle.desktopEditorPadding, + child: WebEditorView( + editorController: controller.richTextWebController.editorController, + arguments: controller.composerArguments.value, + contentViewState: controller.emailContentsViewState.value, + currentWebContent: controller.textEditorWeb, + onInitial: controller.handleInitHtmlEditorWeb, + onChangeContent: controller.onChangeTextEditorWeb, + onFocus: controller.handleOnFocusHtmlEditorWeb, + onUnFocus: controller.handleOnUnFocusHtmlEditorWeb, + onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, + onEditorSettings: controller.richTextWebController.onEditorSettingsChange, + ), + ), + )), + Obx(() { + if (controller.uploadController.listUploadAttachments.isNotEmpty) { + return AttachmentComposerWidget( + listFileUploaded: controller.uploadController.listUploadAttachments, + isCollapsed: controller.isAttachmentCollapsed, + onDeleteAttachmentAction: (fileState) => controller.deleteAttachmentUploaded(fileState.uploadTaskId), + onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed, + ); + } else { + return const SizedBox.shrink(); + } + }), + Obx(() { + if (controller.richTextWebController.isFormattingOptionsEnabled) { + return ToolbarRichTextWebBuilder( + richTextWebController: controller.richTextWebController, + padding: ComposerStyle.richToolbarPadding, + decoration: const BoxDecoration( + color: ComposerStyle.richToolbarColor, + boxShadow: ComposerStyle.richToolbarShadow + ), + ); + } else { + return const SizedBox.shrink(); + } + }) + ], + ), + Obx(() => Align( + alignment: AlignmentDirectional.topCenter, + child: InsertImageLoadingBarWidget( + uploadInlineViewState: controller.uploadController.uploadInlineViewState.value, + viewState: controller.viewState.value, + padding: ComposerStyle.insertImageLoadingBarPadding, ), )), - Obx(() { - if (controller.uploadController.listUploadAttachments.isNotEmpty) { - return AttachmentComposerWidget( - listFileUploaded: controller.uploadController.listUploadAttachments, - isCollapsed: controller.isAttachmentCollapsed, - onDeleteAttachmentAction: (fileState) => controller.deleteAttachmentUploaded(fileState.uploadTaskId), - onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed, - ); - } else { - return const SizedBox.shrink(); - } - }), - Obx(() { - if (controller.richTextWebController.isFormattingOptionsEnabled) { - return ToolbarRichTextWebBuilder( - richTextWebController: controller.richTextWebController, - padding: ComposerStyle.richToolbarPadding, - decoration: const BoxDecoration( - color: ComposerStyle.richToolbarColor, - boxShadow: ComposerStyle.richToolbarShadow - ), - ); - } else { - return const SizedBox.shrink(); - } - }) ], ), ) @@ -461,64 +486,76 @@ class ComposerView extends GetWidget { margin: ComposerStyle.tabletSubjectMargin, ), Expanded( - child: Container( - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide( - color: ComposerStyle.borderColor, - width: 1 - ) - ), - color: ComposerStyle.backgroundEditorColor + child: Container( + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide( + color: ComposerStyle.borderColor, + width: 1 + ) ), - child: Column( - children: [ - Obx(() => Expanded( - child: Padding( - padding: ComposerStyle.tabletEditorPadding, - child: WebEditorView( - editorController: controller.richTextWebController.editorController, - arguments: controller.composerArguments.value, - contentViewState: controller.emailContentsViewState.value, - currentWebContent: controller.textEditorWeb, - onInitial: controller.handleInitHtmlEditorWeb, - onChangeContent: controller.onChangeTextEditorWeb, - onFocus: controller.handleOnFocusHtmlEditorWeb, - onUnFocus: controller.handleOnUnFocusHtmlEditorWeb, - onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, - onEditorSettings: controller.richTextWebController.onEditorSettingsChange, - ), - ), - )), - Obx(() { - if (controller.uploadController.listUploadAttachments.isNotEmpty) { - return AttachmentComposerWidget( - listFileUploaded: controller.uploadController.listUploadAttachments, - isCollapsed: controller.isAttachmentCollapsed, - onDeleteAttachmentAction: (fileState) => controller.deleteAttachmentUploaded(fileState.uploadTaskId), - onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed, - ); - } else { - return const SizedBox.shrink(); - } - }), - Obx(() { - if (controller.richTextWebController.isFormattingOptionsEnabled) { - return ToolbarRichTextWebBuilder( - richTextWebController: controller.richTextWebController, - padding: ComposerStyle.richToolbarPadding, - decoration: const BoxDecoration( - color: ComposerStyle.richToolbarColor, - boxShadow: ComposerStyle.richToolbarShadow + color: ComposerStyle.backgroundEditorColor + ), + child: Stack( + children: [ + Column( + children: [ + Obx(() => Expanded( + child: Padding( + padding: ComposerStyle.tabletEditorPadding, + child: WebEditorView( + editorController: controller.richTextWebController.editorController, + arguments: controller.composerArguments.value, + contentViewState: controller.emailContentsViewState.value, + currentWebContent: controller.textEditorWeb, + onInitial: controller.handleInitHtmlEditorWeb, + onChangeContent: controller.onChangeTextEditorWeb, + onFocus: controller.handleOnFocusHtmlEditorWeb, + onUnFocus: controller.handleOnUnFocusHtmlEditorWeb, + onMouseDown: controller.handleOnMouseDownHtmlEditorWeb, + onEditorSettings: controller.richTextWebController.onEditorSettingsChange, ), - ); - } else { - return const SizedBox.shrink(); - } - }) - ], - ), - ) + ), + )), + Obx(() { + if (controller.uploadController.listUploadAttachments.isNotEmpty) { + return AttachmentComposerWidget( + listFileUploaded: controller.uploadController.listUploadAttachments, + isCollapsed: controller.isAttachmentCollapsed, + onDeleteAttachmentAction: (fileState) => controller.deleteAttachmentUploaded(fileState.uploadTaskId), + onToggleExpandAttachmentAction: (isCollapsed) => controller.isAttachmentCollapsed = isCollapsed, + ); + } else { + return const SizedBox.shrink(); + } + }), + Obx(() { + if (controller.richTextWebController.isFormattingOptionsEnabled) { + return ToolbarRichTextWebBuilder( + richTextWebController: controller.richTextWebController, + padding: ComposerStyle.richToolbarPadding, + decoration: const BoxDecoration( + color: ComposerStyle.richToolbarColor, + boxShadow: ComposerStyle.richToolbarShadow + ), + ); + } else { + return const SizedBox.shrink(); + } + }) + ], + ), + Obx(() => Align( + alignment: AlignmentDirectional.topCenter, + child: InsertImageLoadingBarWidget( + uploadInlineViewState: controller.uploadController.uploadInlineViewState.value, + viewState: controller.viewState.value, + padding: ComposerStyle.insertImageLoadingBarPadding, + ), + )), + ], + ), + ) ), Obx(() => BottomBarComposerWidget( isCodeViewEnabled: controller.richTextWebController.codeViewEnabled, diff --git a/lib/features/composer/presentation/styles/composer_style.dart b/lib/features/composer/presentation/styles/composer_style.dart index 8e7cbf6d3..d88eca6c8 100644 --- a/lib/features/composer/presentation/styles/composer_style.dart +++ b/lib/features/composer/presentation/styles/composer_style.dart @@ -33,6 +33,7 @@ class ComposerStyle { static const EdgeInsetsGeometry mobileSubjectPadding = EdgeInsetsDirectional.only(end: 16, top: 12, bottom: 12); static const EdgeInsetsGeometry mobileEditorPadding = EdgeInsetsDirectional.symmetric(horizontal: 12); static const EdgeInsetsGeometry popupItemPadding = EdgeInsetsDirectional.symmetric(horizontal: 12); + static const EdgeInsetsGeometry insertImageLoadingBarPadding = EdgeInsetsDirectional.only(top: 12); static const TextStyle popupItemTextStyle = TextStyle( color: Colors.black, diff --git a/lib/features/composer/presentation/styles/mobile/mobile_attachment_composer_widget_style.dart b/lib/features/composer/presentation/styles/mobile/mobile_attachment_composer_widget_style.dart index ef83ffd0c..4c401ff6e 100644 --- a/lib/features/composer/presentation/styles/mobile/mobile_attachment_composer_widget_style.dart +++ b/lib/features/composer/presentation/styles/mobile/mobile_attachment_composer_widget_style.dart @@ -1,17 +1,10 @@ -import 'package:core/presentation/extensions/color_extension.dart'; import 'package:flutter/material.dart'; class MobileAttachmentComposerWidgetStyle { static const double listItemSpace = 8; - - static const Color backgroundColor = Colors.white; + static const int maxItemRow = 2; + static const double listItemHeight = 50; static const EdgeInsetsGeometry padding = EdgeInsetsDirectional.symmetric(vertical: 8, horizontal: 16); - static const EdgeInsetsGeometry showMoreMargin = EdgeInsetsDirectional.only(top: 8); - - static const TextStyle showMoreButtonTextStyle = TextStyle( - fontSize: 15, - color: AppColor.primaryColor, - fontWeight: FontWeight.w500 - ); + static const EdgeInsetsGeometry itemMargin = EdgeInsetsDirectional.only(top: 8); } \ No newline at end of file diff --git a/lib/features/composer/presentation/view/mobile/mobile_container_view.dart b/lib/features/composer/presentation/view/mobile/mobile_container_view.dart index 7e0bea97d..3ba955d0d 100644 --- a/lib/features/composer/presentation/view/mobile/mobile_container_view.dart +++ b/lib/features/composer/presentation/view/mobile/mobile_container_view.dart @@ -2,7 +2,7 @@ import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; import 'package:get/get.dart'; -import 'package:rich_text_composer/rich_text_composer.dart'; +import 'package:rich_text_composer/rich_text_composer.dart' as rich_composer; import 'package:rich_text_composer/views/widgets/rich_text_keyboard_toolbar.dart'; import 'package:tmail_ui_user/features/composer/presentation/styles/mobile/mobile_container_view_style.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -12,11 +12,12 @@ typedef OnInsertImageAction = Function(BoxConstraints constraints); class MobileContainerView extends StatelessWidget { final Widget Function(BuildContext context) childBuilder; - final RichTextController keyboardRichTextController; + final rich_composer.RichTextController keyboardRichTextController; final VoidCallback onCloseViewAction; final VoidCallback? onAttachFileAction; final OnInsertImageAction? onInsertImageAction; final VoidCallback? onClearFocusAction; + final Color? backgroundColor; final _responsiveUtils = Get.find(); @@ -28,6 +29,7 @@ class MobileContainerView extends StatelessWidget { this.onAttachFileAction, this.onInsertImageAction, this.onClearFocusAction, + this.backgroundColor, }); @override @@ -40,11 +42,11 @@ class MobileContainerView extends StatelessWidget { child: GestureDetector( onTap: onClearFocusAction, child: Scaffold( - backgroundColor: MobileContainerViewStyle.outSideBackgroundColor, + backgroundColor: backgroundColor ?? MobileContainerViewStyle.outSideBackgroundColor, resizeToAvoidBottomInset: false, body: LayoutBuilder(builder: (context, constraints) { return KeyboardVisibilityBuilder(builder: (context, isKeyboardVisible) { - return KeyboardRichText( + return rich_composer.KeyboardRichText( richTextController: keyboardRichTextController, keyBroadToolbar: RichTextKeyboardToolBar( backgroundKeyboardToolBarColor: MobileContainerViewStyle.keyboardToolbarBackgroundColor, diff --git a/lib/features/composer/presentation/widgets/attachment_item_composer_widget.dart b/lib/features/composer/presentation/widgets/attachment_item_composer_widget.dart index 68f87578f..42084ef58 100644 --- a/lib/features/composer/presentation/widgets/attachment_item_composer_widget.dart +++ b/lib/features/composer/presentation/widgets/attachment_item_composer_widget.dart @@ -41,6 +41,7 @@ class AttachmentItemComposerWidget extends StatelessWidget with AppLoaderMixin { ), width: AttachmentItemComposerWidgetStyle.width, padding: AttachmentItemComposerWidgetStyle.padding, + margin: itemMargin, child: Row( children: [ Expanded( diff --git a/lib/features/composer/presentation/widgets/insert_image_loading_bar_widget.dart b/lib/features/composer/presentation/widgets/insert_image_loading_bar_widget.dart new file mode 100644 index 000000000..43debb9c3 --- /dev/null +++ b/lib/features/composer/presentation/widgets/insert_image_loading_bar_widget.dart @@ -0,0 +1,55 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:dartz/dartz.dart'; +import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/features/base/widget/circle_loading_widget.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_base64_state.dart'; +import 'package:tmail_ui_user/features/upload/domain/state/attachment_upload_state.dart'; + +class InsertImageLoadingBarWidget extends StatelessWidget { + + final Either viewState; + final Either uploadInlineViewState; + final EdgeInsetsGeometry? padding; + + const InsertImageLoadingBarWidget({ + super.key, + required this.viewState, + required this.uploadInlineViewState, + this.padding, + }); + + @override + Widget build(BuildContext context) { + return uploadInlineViewState.fold( + (failure) { + return viewState.fold( + (failure) => const SizedBox.shrink(), + (success) { + if (success is DownloadingImageAsBase64) { + return CircleLoadingWidget(padding: padding); + } else { + return const SizedBox.shrink(); + } + } + ); + }, + (success) { + if (success is UploadingAttachmentUploadState) { + return CircleLoadingWidget(padding: padding); + } else { + return viewState.fold( + (failure) => const SizedBox.shrink(), + (success) { + if (success is DownloadingImageAsBase64) { + return CircleLoadingWidget(padding: padding); + } else { + return const SizedBox.shrink(); + } + } + ); + } + } + ); + } +} diff --git a/lib/features/composer/presentation/widgets/mobile/mobile_attachment_composer_widget.dart b/lib/features/composer/presentation/widgets/mobile/mobile_attachment_composer_widget.dart index cc6364709..e219c6f3f 100644 --- a/lib/features/composer/presentation/widgets/mobile/mobile_attachment_composer_widget.dart +++ b/lib/features/composer/presentation/widgets/mobile/mobile_attachment_composer_widget.dart @@ -1,83 +1,72 @@ -import 'package:core/presentation/views/button/tmail_button_widget.dart'; +import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:core/presentation/views/list/sliver_grid_delegate_fixed_height.dart'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/composer/presentation/styles/attachment_item_composer_widget_style.dart'; import 'package:tmail_ui_user/features/composer/presentation/styles/mobile/mobile_attachment_composer_widget_style.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_item_composer_widget.dart'; import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -typedef OnShowMoreAttachmentAction = void Function(bool isShowMore); - -class MobileAttachmentComposerWidget extends StatefulWidget { +class MobileAttachmentComposerWidget extends StatelessWidget { final List listFileUploaded; - final bool isShowMore; final OnDeleteAttachmentAction onDeleteAttachmentAction; - final OnShowMoreAttachmentAction onShowMoreAttachmentAction; - const MobileAttachmentComposerWidget({ + final _responsiveUtils = Get.find(); + + MobileAttachmentComposerWidget({ super.key, required this.listFileUploaded, - required this.isShowMore, required this.onDeleteAttachmentAction, - required this.onShowMoreAttachmentAction, }); - @override - State createState() => _MobileAttachmentComposerWidgetState(); -} - -class _MobileAttachmentComposerWidgetState extends State { - - static const int _maxDisplayedItem = 6; - - bool _isShowMore = false; - int _currentCountDisplayed = _maxDisplayedItem; - - @override - void initState() { - super.initState(); - _isShowMore = widget.isShowMore; - if (_isShowMore) { - _currentCountDisplayed = widget.listFileUploaded.length; - } else { - _currentCountDisplayed = widget.listFileUploaded.length > 6 - ? 6 - : widget.listFileUploaded.length; - } - } - @override Widget build(BuildContext context) { - final displayedFiles = widget.listFileUploaded.sublist(0, _currentCountDisplayed); - return Container( - color: MobileAttachmentComposerWidgetStyle.backgroundColor, - width: double.infinity, padding: MobileAttachmentComposerWidgetStyle.padding, + width: double.infinity, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Wrap( - spacing: MobileAttachmentComposerWidgetStyle.listItemSpace, - runSpacing: MobileAttachmentComposerWidgetStyle.listItemSpace, - children: displayedFiles - .map((file) => AttachmentItemComposerWidget( - fileState: file, - onDeleteAttachmentAction: widget.onDeleteAttachmentAction - )) - .toList(), - ), - if (!_isShowMore) - TMailButtonWidget.fromText( - text: AppLocalizations.of(context).showMoreAttachment(widget.listFileUploaded.length), - textStyle: MobileAttachmentComposerWidgetStyle.showMoreButtonTextStyle, - margin: MobileAttachmentComposerWidgetStyle.showMoreMargin, - backgroundColor: Colors.transparent, - onTapActionCallback: () { - setState(() => _isShowMore = true); - widget.onShowMoreAttachmentAction(_isShowMore); - }, + if (_responsiveUtils.isLandscapeMobile(context)) + SizedBox( + width: _responsiveUtils.getSizeScreenWidth(context) * 0.7, + child: GridView.builder( + reverse: true, + primary: false, + shrinkWrap: true, + itemCount: listFileUploaded.length, + gridDelegate: const SliverGridDelegateFixedHeight( + height: MobileAttachmentComposerWidgetStyle.listItemHeight, + crossAxisCount: MobileAttachmentComposerWidgetStyle.maxItemRow, + crossAxisSpacing: MobileAttachmentComposerWidgetStyle.listItemSpace, + ), + itemBuilder: (context, index) { + return AttachmentItemComposerWidget( + fileState: listFileUploaded[index], + itemMargin: MobileAttachmentComposerWidgetStyle.itemMargin, + onDeleteAttachmentAction: onDeleteAttachmentAction + ); + } + ), + ) + else + SizedBox( + width: AttachmentItemComposerWidgetStyle.width, + child: ListView.builder( + reverse: true, + shrinkWrap: true, + primary: false, + itemCount: listFileUploaded.length, + itemBuilder: (context, index) { + return AttachmentItemComposerWidget( + fileState: listFileUploaded[index], + itemMargin: MobileAttachmentComposerWidgetStyle.itemMargin, + onDeleteAttachmentAction: onDeleteAttachmentAction + ); + } + ), ) ] ), diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart index 8d9df719c..393f91bc1 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -291,8 +291,7 @@ class EmailView extends GetWidget { } }), Obx(() => EmailViewLoadingBarWidget( - viewState: controller.emailLoadedViewState.value, - selectedEmail: presentationEmail + viewState: controller.emailLoadedViewState.value )), if (calendarEvent != null) Column( diff --git a/lib/features/email/presentation/widgets/email_view_loading_bar_widget.dart b/lib/features/email/presentation/widgets/email_view_loading_bar_widget.dart index 644712178..f0054755a 100644 --- a/lib/features/email/presentation/widgets/email_view_loading_bar_widget.dart +++ b/lib/features/email/presentation/widgets/email_view_loading_bar_widget.dart @@ -2,20 +2,17 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; import 'package:dartz/dartz.dart'; import 'package:flutter/material.dart'; -import 'package:model/email/presentation_email.dart'; import 'package:tmail_ui_user/features/base/widget/cupertino_loading_widget.dart'; import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/parse_calendar_event_state.dart'; class EmailViewLoadingBarWidget extends StatelessWidget { - final PresentationEmail selectedEmail; final Either viewState; const EmailViewLoadingBarWidget({ super.key, required this.viewState, - required this.selectedEmail }); @override