diff --git a/lib/features/base/styles/popup_item_widget_style.dart b/lib/features/base/styles/popup_item_widget_style.dart index 6419e3714..42f9f6338 100644 --- a/lib/features/base/styles/popup_item_widget_style.dart +++ b/lib/features/base/styles/popup_item_widget_style.dart @@ -1,3 +1,4 @@ +import 'package:core/presentation/utils/theme_utils.dart'; import 'package:flutter/material.dart'; class PopupItemWidgetStyle { @@ -5,14 +6,12 @@ class PopupItemWidgetStyle { static const double selectedIconSize = 16; static const double space = 16; static const double height = 48; - static const double minWidth = 256; + static const double maxWidth = 300; - static const EdgeInsetsGeometry padding = EdgeInsets.symmetric(horizontal: 20, vertical: 16); - static const EdgeInsetsGeometry iconSelectedPadding = EdgeInsetsDirectional.only(start: 12); + static const EdgeInsetsGeometry iconSelectedPadding = + EdgeInsetsDirectional.only(start: 16); - static const TextStyle labelTextStyle = TextStyle( - fontSize: 17, - fontWeight: FontWeight.normal, - color: Colors.black + static final TextStyle labelTextStyle = ThemeUtils.textStyleBodyBody3( + color: Colors.black, ); } \ 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 99e32fd4f..28f0e1f1e 100644 --- a/lib/features/base/widget/popup_item_widget.dart +++ b/lib/features/base/widget/popup_item_widget.dart @@ -40,32 +40,37 @@ class PopupItemWidget extends StatelessWidget { onTap: onCallbackAction, child: Container( height: PopupItemWidgetStyle.height, - constraints: const BoxConstraints(minWidth: PopupItemWidgetStyle.minWidth), + constraints: const BoxConstraints( + maxWidth: PopupItemWidgetStyle.maxWidth, + ), padding: padding, - child: Row(children: [ - SvgPicture.asset( - iconAction, - width: iconSize ?? PopupItemWidgetStyle.iconSize, - height: iconSize ?? PopupItemWidgetStyle.iconSize, - fit: BoxFit.fill, - colorFilter: colorIcon?.asFilter() - ), - SizedBox(width: iconSpace ?? PopupItemWidgetStyle.space), - Expanded(child: Text( - nameAction, - style: styleName ?? PopupItemWidgetStyle.labelTextStyle - )), - if (isSelected == true && selectedIcon != null) - Padding( - padding: PopupItemWidgetStyle.iconSelectedPadding, - child: SvgPicture.asset( - selectedIcon!, - width: PopupItemWidgetStyle.selectedIconSize, - height: PopupItemWidgetStyle.selectedIconSize, - fit: BoxFit.fill - ), - ) - ]), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset( + iconAction, + width: iconSize ?? PopupItemWidgetStyle.iconSize, + height: iconSize ?? PopupItemWidgetStyle.iconSize, + fit: BoxFit.fill, + colorFilter: colorIcon?.asFilter() + ), + SizedBox(width: iconSpace ?? PopupItemWidgetStyle.space), + Expanded(child: Text( + nameAction, + style: styleName ?? PopupItemWidgetStyle.labelTextStyle + )), + if (isSelected == true && selectedIcon != null) + Padding( + padding: PopupItemWidgetStyle.iconSelectedPadding, + child: SvgPicture.asset( + selectedIcon!, + width: PopupItemWidgetStyle.selectedIconSize, + height: PopupItemWidgetStyle.selectedIconSize, + fit: BoxFit.fill, + ), + ) + ], + ), ) ), ), diff --git a/lib/features/base/widget/popup_menu_overlay_widget.dart b/lib/features/base/widget/popup_menu_overlay_widget.dart index e82d9873b..dd29bf7aa 100644 --- a/lib/features/base/widget/popup_menu_overlay_widget.dart +++ b/lib/features/base/widget/popup_menu_overlay_widget.dart @@ -34,15 +34,18 @@ class PopupMenuOverlayWidget extends StatelessWidget { controller: controller, menuBuilder: () { return Material( - elevation: elevation ?? 10, - borderRadius: BorderRadius.circular(borderRadius ?? 12), + elevation: elevation ?? 8, + borderRadius: BorderRadius.all(Radius.circular(borderRadius ?? 6)), color: backgroundColor ?? Colors.white, child: PointerInterceptor( child: Container( decoration: BoxDecoration( - color: backgroundColor ?? Colors.white, - borderRadius: BorderRadius.circular(borderRadius ?? 12)), - padding: padding, + color: backgroundColor ?? Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(borderRadius ?? 6), + ), + ), + padding: padding ?? const EdgeInsets.symmetric(vertical: 8), clipBehavior: Clip.antiAlias, child: arrangeAsList ? IntrinsicWidth(child: Column(children: listButtonAction)) @@ -55,7 +58,7 @@ class PopupMenuOverlayWidget extends StatelessWidget { position: position, barrierColor: Colors.transparent, arrowSize: 0.0, - verticalMargin: 8, + verticalMargin: 2.0, child: iconButton, ); } diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index 07796c7a0..1146caec5 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -7,9 +7,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:model/email/prefix_email_address.dart'; -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/extensions/handle_content_height_exceeded_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/handle_open_context_menu_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/mark_as_important_extension.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'; @@ -29,7 +29,6 @@ import 'package:tmail_ui_user/features/composer/presentation/widgets/subject_com import 'package:tmail_ui_user/features/composer/presentation/widgets/web/from_composer_drop_down_widget.dart'; import 'package:tmail_ui_user/features/email/presentation/widgets/view_entire_message_with_message_clipped_widget.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class ComposerView extends GetWidget { @@ -57,11 +56,7 @@ class ComposerView extends GetWidget { onCloseViewAction: () => controller.handleClickCloseComposer(context), sendMessageAction: () => controller.handleClickSendButton(context), openContextMenuAction: (position) { - controller.openPopupMenuAction( - context, - position, - _createMoreOptionPopupItems(context), - ); + controller.handleOpenContextMenu(context, position); }, isNetworkConnectionAvailable: controller.isNetworkConnectionAvailable, attachFileAction: () => controller.openPickAttachmentMenu( @@ -82,11 +77,7 @@ class ComposerView extends GetWidget { onCloseViewAction: () => controller.handleClickCloseComposer(context), sendMessageAction: () => controller.handleClickSendButton(context), openContextMenuAction: (position) { - controller.openPopupMenuAction( - context, - position, - _createMoreOptionPopupItems(context), - ); + controller.handleOpenContextMenu(context, position); }, isNetworkConnectionAvailable: controller.isNetworkConnectionAvailable, attachFileAction: () => controller.openPickAttachmentMenu( @@ -509,85 +500,4 @@ class ComposerView extends GetWidget { ..onActionClick((_) => controller.openFilePickerByType(context, FileType.any))) .build(); } - - List _createMoreOptionPopupItems(BuildContext context) { - return [ - PopupMenuItem( - padding: EdgeInsets.zero, - child: PopupItemWidget( - key: const Key('mark_as_important_popup_item'), - iconAction: controller.imagePaths.icMarkAsImportant, - nameAction: AppLocalizations.of(context).markAsImportant, - styleName: ComposerStyle.popupItemTextStyle, - padding: ComposerStyle.popupItemPadding, - colorIcon: ComposerStyle.popupItemIconColor, - selectedIcon: controller.imagePaths.icFilterSelected, - isSelected: controller.isMarkAsImportant.value, - onCallbackAction: () { - popBack(); - controller.toggleMarkAsImportant(context); - }, - ), - ), - PopupMenuItem( - padding: EdgeInsets.zero, - child: PopupItemWidget( - key: const Key('read_receipt_popup_item'), - iconAction: controller.imagePaths.icReadReceipt, - nameAction: AppLocalizations.of(context).requestReadReceipt, - styleName: ComposerStyle.popupItemTextStyle, - padding: ComposerStyle.popupItemPadding, - colorIcon: ComposerStyle.popupItemIconColor, - selectedIcon: controller.imagePaths.icFilterSelected, - isSelected: controller.hasRequestReadReceipt.value, - onCallbackAction: () { - popBack(); - controller.toggleRequestReadReceipt(context); - } - ) - ), - PopupMenuItem( - padding: EdgeInsets.zero, - child: PopupItemWidget( - key: const Key('save_as_draft_popup_item'), - iconAction: controller.imagePaths.icSaveToDraft, - nameAction: AppLocalizations.of(context).saveAsDraft, - colorIcon: ComposerStyle.popupItemIconColor, - styleName: ComposerStyle.popupItemTextStyle, - padding: ComposerStyle.popupItemPadding, - onCallbackAction: () { - popBack(); - controller.handleClickSaveAsDraftsButton(context); - } - ) - ), - PopupMenuItem( - padding: EdgeInsets.zero, - child: PopupItemWidget( - iconAction: controller.imagePaths.icSaveToDraft, - nameAction: AppLocalizations.of(context).saveAsTemplate, - colorIcon: ComposerStyle.popupItemIconColor, - styleName: ComposerStyle.popupItemTextStyle, - padding: ComposerStyle.popupItemPadding, - onCallbackAction: () { - popBack(); - controller.handleClickSaveAsTemplateButton(context); - } - ) - ), - PopupMenuItem( - padding: EdgeInsets.zero, - child: PopupItemWidget( - iconAction: controller.imagePaths.icDeleteMailbox, - nameAction: AppLocalizations.of(context).delete, - styleName: ComposerStyle.popupItemTextStyle, - padding: ComposerStyle.popupItemPadding, - onCallbackAction: () { - popBack(); - controller.handleClickDeleteComposer(context); - }, - ) - ), - ]; - } } \ No newline at end of file diff --git a/lib/features/composer/presentation/extensions/handle_open_context_menu_extension.dart b/lib/features/composer/presentation/extensions/handle_open_context_menu_extension.dart new file mode 100644 index 000000000..3e481a1c3 --- /dev/null +++ b/lib/features/composer/presentation/extensions/handle_open_context_menu_extension.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/features/base/widget/popup_menu/popup_menu_item_action_widget.dart'; +import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/mark_as_important_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/composer_action_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/popup_menu_item_composer_type_action.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; +import 'package:tmail_ui_user/main/routes/route_navigation.dart'; + +extension HandleOpenContextMenuExtension on ComposerController { + void handleOpenContextMenu(BuildContext context, RelativeRect position) { + final popupMenuItems = ComposerActionType.values.map((actionType) { + return PopupMenuItem( + padding: EdgeInsets.zero, + child: PopupMenuItemActionWidget( + key: actionType.getContextMenuItemKey(), + menuAction: PopupMenuItemComposerTypeAction( + actionType, + AppLocalizations.of(context), + imagePaths, + ), + menuActionClick: (menuAction) { + popBack(); + _handleComposerActionTypeClick(context, menuAction.action); + }, + ), + ); + }).toList(); + + openPopupMenuAction(context, position, popupMenuItems); + } + + void _handleComposerActionTypeClick( + BuildContext context, + ComposerActionType actionType, + ) { + switch (actionType) { + case ComposerActionType.markAsImportant: + toggleMarkAsImportant(context); + break; + case ComposerActionType.requestReadReceipt: + toggleRequestReadReceipt(context); + break; + case ComposerActionType.saveAsDraft: + handleClickSaveAsDraftsButton(context); + break; + case ComposerActionType.saveAsTemplate: + handleClickSaveAsTemplateButton(context); + break; + case ComposerActionType.delete: + handleClickDeleteComposer(context); + break; + } + } +} diff --git a/lib/features/composer/presentation/model/composer_action_type.dart b/lib/features/composer/presentation/model/composer_action_type.dart new file mode 100644 index 000000000..2acef0a01 --- /dev/null +++ b/lib/features/composer/presentation/model/composer_action_type.dart @@ -0,0 +1,75 @@ +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +enum ComposerActionType { + markAsImportant, + requestReadReceipt, + saveAsDraft, + saveAsTemplate, + delete; + + String getContextMenuTitle(AppLocalizations appLocalizations) { + switch (this) { + case ComposerActionType.markAsImportant: + return appLocalizations.markAsImportant; + case ComposerActionType.requestReadReceipt: + return appLocalizations.requestReadReceipt; + case ComposerActionType.saveAsDraft: + return appLocalizations.saveAsDraft; + case ComposerActionType.saveAsTemplate: + return appLocalizations.saveAsTemplate; + case ComposerActionType.delete: + return appLocalizations.delete; + } + } + + String getContextMenuIcon(ImagePaths imagePath) { + switch (this) { + case ComposerActionType.markAsImportant: + return imagePath.icMarkAsImportant; + case ComposerActionType.requestReadReceipt: + return imagePath.icReadReceipt; + case ComposerActionType.saveAsDraft: + return imagePath.icSaveToDraft; + case ComposerActionType.saveAsTemplate: + return imagePath.icSaveToDraft; + case ComposerActionType.delete: + return imagePath.icDeleteMailbox; + } + } + + Color getContextMenuTitleColor() { + switch (this) { + case ComposerActionType.delete: + return AppColor.redFF3347; + default: + return Colors.black; + } + } + + Color getContextMenuIconColor() { + switch (this) { + case ComposerActionType.delete: + return AppColor.redFF3347; + default: + return AppColor.steelGrayA540; + } + } + + Key getContextMenuItemKey() { + switch (this) { + case ComposerActionType.markAsImportant: + return const Key('mark_as_important_popup_item'); + case ComposerActionType.requestReadReceipt: + return const Key('read_receipt_popup_item'); + case ComposerActionType.saveAsDraft: + return const Key('save_as_draft_popup_item'); + case ComposerActionType.saveAsTemplate: + return const Key('save_as_template_popup_item'); + case ComposerActionType.delete: + return const Key('delete_popup_item'); + } + } +} diff --git a/lib/features/composer/presentation/model/popup_menu_item_composer_type_action.dart b/lib/features/composer/presentation/model/popup_menu_item_composer_type_action.dart new file mode 100644 index 000000000..5c0eb9bd7 --- /dev/null +++ b/lib/features/composer/presentation/model/popup_menu_item_composer_type_action.dart @@ -0,0 +1,29 @@ +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/features/base/model/popup_menu_item_action.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/composer_action_type.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +class PopupMenuItemComposerTypeAction + extends PopupMenuItemActionRequiredIcon { + final AppLocalizations appLocalizations; + final ImagePaths imagePaths; + + PopupMenuItemComposerTypeAction( + super.action, + this.appLocalizations, + this.imagePaths, + ); + + @override + String get actionIcon => action.getContextMenuIcon(imagePaths); + + @override + String get actionName => action.getContextMenuTitle(appLocalizations); + + @override + Color get actionIconColor => action.getContextMenuIconColor(); + + @override + Color get actionNameColor => action.getContextMenuTitleColor(); +} diff --git a/lib/features/composer/presentation/styles/mobile_app_bar_composer_widget_style.dart b/lib/features/composer/presentation/styles/mobile_app_bar_composer_widget_style.dart index 73c3fcbd3..03f5910d8 100644 --- a/lib/features/composer/presentation/styles/mobile_app_bar_composer_widget_style.dart +++ b/lib/features/composer/presentation/styles/mobile_app_bar_composer_widget_style.dart @@ -1,5 +1,6 @@ import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/utils/theme_utils.dart'; import 'package:flutter/material.dart'; class MobileAppBarComposerWidgetStyle { @@ -20,9 +21,7 @@ class MobileAppBarComposerWidgetStyle { static const EdgeInsetsGeometry richTextIconPadding = EdgeInsetsDirectional.all(5); static const EdgeInsetsGeometry popupItemPadding = EdgeInsetsDirectional.symmetric(horizontal: 12); - static const TextStyle popupItemTextStyle = TextStyle( + static final TextStyle popupItemTextStyle = ThemeUtils.textStyleBodyBody3( color: Colors.black, - fontSize: 16, - fontWeight: FontWeight.w500, ); } \ No newline at end of file diff --git a/lib/features/composer/presentation/styles/web/bottom_bar_composer_widget_style.dart b/lib/features/composer/presentation/styles/web/bottom_bar_composer_widget_style.dart index ba72132a3..fa3659c67 100644 --- a/lib/features/composer/presentation/styles/web/bottom_bar_composer_widget_style.dart +++ b/lib/features/composer/presentation/styles/web/bottom_bar_composer_widget_style.dart @@ -1,6 +1,7 @@ import 'package:core/presentation/constants/constants_ui.dart'; import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/utils/theme_utils.dart'; import 'package:flutter/material.dart'; class BottomBarComposerWidgetStyle { @@ -33,9 +34,7 @@ class BottomBarComposerWidgetStyle { color: Colors.white, letterSpacing: -0.41, ); - static const TextStyle popupItemTextStyle = TextStyle( + static final TextStyle popupItemTextStyle = ThemeUtils.textStyleBodyBody3( color: Colors.black, - fontSize: 16, - fontWeight: FontWeight.w500, ); } \ No newline at end of file diff --git a/lib/features/composer/presentation/widgets/web/mobile_responsive_app_bar_composer_widget.dart b/lib/features/composer/presentation/widgets/web/mobile_responsive_app_bar_composer_widget.dart index 98f4a9730..936fdef2f 100644 --- a/lib/features/composer/presentation/widgets/web/mobile_responsive_app_bar_composer_widget.dart +++ b/lib/features/composer/presentation/widgets/web/mobile_responsive_app_bar_composer_widget.dart @@ -1,3 +1,4 @@ +import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/utils/platform_info.dart'; @@ -202,8 +203,10 @@ class MobileResponsiveAppBarComposerWidget extends StatelessWidget { PopupItemWidget( iconAction: imagePaths.icDeleteMailbox, nameAction: AppLocalizations.of(context).delete, - colorIcon: MobileAppBarComposerWidgetStyle.popupItemIconColor, - styleName: MobileAppBarComposerWidgetStyle.popupItemTextStyle, + colorIcon: AppColor.redFF3347, + styleName: MobileAppBarComposerWidgetStyle + .popupItemTextStyle + .copyWith(color: AppColor.redFF3347), padding: MobileAppBarComposerWidgetStyle.popupItemPadding, onCallbackAction: () { menuMoreOptionController.hideMenu(); diff --git a/lib/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart b/lib/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart index a207f2e1c..39a2eaa14 100644 --- a/lib/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart +++ b/lib/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart @@ -1,5 +1,7 @@ import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:custom_pop_up_menu/custom_pop_up_menu.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; @@ -22,6 +24,7 @@ class ToolbarRichTextWebBuilder extends StatelessWidget with RichTextButtonMixin final RichTextWebController richTextWebController; final ImagePaths _imagePaths = Get.find(); + final ResponsiveUtils _responsiveUtils = Get.find(); final EdgeInsetsGeometry? padding; final List? extendedOption; final AlignmentGeometry? alignment; @@ -224,6 +227,9 @@ class ToolbarRichTextWebBuilder extends StatelessWidget with RichTextButtonMixin tooltip: RichTextStyleType.paragraph.getTooltipButton(context) ) ), + position: _responsiveUtils.isMobile(context) + ? PreferredPosition.top + : PreferredPosition.bottom, ), ), AbsorbPointer( @@ -248,6 +254,9 @@ class ToolbarRichTextWebBuilder extends StatelessWidget with RichTextButtonMixin tooltip: RichTextStyleType.orderList.getTooltipButton(context) ) ), + position: _responsiveUtils.isMobile(context) + ? PreferredPosition.top + : PreferredPosition.bottom, ), ) ]