diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart index 71d03e4a2..aafe4a73d 100644 --- a/core/lib/presentation/extensions/color_extension.dart +++ b/core/lib/presentation/extensions/color_extension.dart @@ -268,6 +268,8 @@ extension AppColor on Color { static const lightGrayEAEDF2 = Color(0xFFEAEDF2); static const lightIconTertiary = Color(0xFFB8C1CC); static const gray6D7885 = Color(0xFF6D7885); + static const m3Primary = Color(0xFF0A84FF); + static const m3Primary95 = Color(0xFFE3F1FF); static const mapGradientColor = [ [Color(0xFF21D4FD), Color(0xFFB721FF)], diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart index da7fd8159..d0cf84e87 100644 --- a/lib/features/composer/presentation/composer_view_web.dart +++ b/lib/features/composer/presentation/composer_view_web.dart @@ -26,7 +26,7 @@ import 'package:tmail_ui_user/features/composer/presentation/widgets/web/desktop import 'package:tmail_ui_user/features/composer/presentation/widgets/web/from_composer_drop_down_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/web/local_file_drop_zone_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/web/mobile_responsive_app_bar_composer_widget.dart'; -import 'package:tmail_ui_user/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/web/toolbar_rich_text_widget.dart'; class ComposerView extends GetWidget { @@ -268,13 +268,15 @@ class ComposerView extends GetWidget { }), Obx(() { if (controller.richTextWebController!.isFormattingOptionsEnabled) { - return ToolbarRichTextWebBuilder( - richTextWebController: controller.richTextWebController!, + return ToolbarRichTextWidget( + richTextController: controller.richTextWebController!, + imagePaths: controller.imagePaths, padding: ComposerStyle.richToolbarPadding, decoration: const BoxDecoration( color: ComposerStyle.richToolbarColor, - boxShadow: ComposerStyle.richToolbarShadow + boxShadow: ComposerStyle.richToolbarShadow, ), + isMobile: controller.responsiveUtils.isMobile(context), ); } else { return const SizedBox.shrink(); @@ -560,13 +562,15 @@ class ComposerView extends GetWidget { }), Obx(() { if (controller.richTextWebController!.isFormattingOptionsEnabled) { - return ToolbarRichTextWebBuilder( - richTextWebController: controller.richTextWebController!, + return ToolbarRichTextWidget( + richTextController: controller.richTextWebController!, + imagePaths: controller.imagePaths, padding: ComposerStyle.richToolbarPadding, decoration: const BoxDecoration( color: ComposerStyle.richToolbarColor, - boxShadow: ComposerStyle.richToolbarShadow + boxShadow: ComposerStyle.richToolbarShadow, ), + isMobile: controller.responsiveUtils.isMobile(context), ); } else { return const SizedBox.shrink(); @@ -878,13 +882,15 @@ class ComposerView extends GetWidget { }), Obx(() { if (controller.richTextWebController!.isFormattingOptionsEnabled) { - return ToolbarRichTextWebBuilder( - richTextWebController: controller.richTextWebController!, + return ToolbarRichTextWidget( + richTextController: controller.richTextWebController!, + imagePaths: controller.imagePaths, padding: ComposerStyle.richToolbarPadding, decoration: const BoxDecoration( color: ComposerStyle.richToolbarColor, - boxShadow: ComposerStyle.richToolbarShadow + boxShadow: ComposerStyle.richToolbarShadow, ), + isMobile: controller.responsiveUtils.isMobile(context), ); } else { return const SizedBox.shrink(); diff --git a/lib/features/composer/presentation/controller/rich_text_web_controller.dart b/lib/features/composer/presentation/controller/rich_text_web_controller.dart index 93bd5f6f5..636b7e96e 100644 --- a/lib/features/composer/presentation/controller/rich_text_web_controller.dart +++ b/lib/features/composer/presentation/controller/rich_text_web_controller.dart @@ -240,6 +240,10 @@ class RichTextWebController extends BaseRichTextController { final newCodeViewState = isActivated ? CodeViewState.disabled : CodeViewState.enabled; codeViewState.value = newCodeViewState; editorController.toggleCodeView(); + + if (codeViewEnabled) { + formattingOptionsState.value = FormattingOptionsState.disabled; + } } void applyHeaderStyle(HeaderStyleType? newStyle) { diff --git a/lib/features/composer/presentation/mixin/rich_text_button_mixin.dart b/lib/features/composer/presentation/mixin/rich_text_button_mixin.dart deleted file mode 100644 index 205018f63..000000000 --- a/lib/features/composer/presentation/mixin/rich_text_button_mixin.dart +++ /dev/null @@ -1,140 +0,0 @@ -import 'package:core/presentation/extensions/color_extension.dart'; -import 'package:core/presentation/resources/image_paths.dart'; -import 'package:core/presentation/views/button/icon_button_web.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; - -mixin RichTextButtonMixin { - - final _imagePaths = Get.find(); - - Widget buildWrapIconStyleText({ - required Widget icon, - VoidCallback? onTap, - bool isSelected = false, - bool hasDropdown = true, - EdgeInsets? padding, - double? spacing, - String tooltip = '', - }){ - late Widget buttonIcon; - if (tooltip.isNotEmpty) { - buttonIcon = Tooltip( - message: tooltip, - child: Container( - padding: padding ?? const EdgeInsets.symmetric(horizontal: 5, vertical: 5), - decoration: BoxDecoration( - color: isSelected == true - ? AppColor.colorBackgroundWrapIconStyleCode - : Colors.white, - border: Border.all( - color: AppColor.colorBorderWrapIconStyleCode, - width: 0.5), - borderRadius: BorderRadius.circular(8)), - child: hasDropdown - ? Row( - mainAxisSize: MainAxisSize.min, - children: [ - icon, - if (spacing != null) SizedBox(width: spacing), - SvgPicture.asset(_imagePaths.icStyleArrowDown) - ]) - : icon, - ), - ); - } else { - buttonIcon = Container( - padding: padding ?? const EdgeInsets.symmetric(horizontal: 5, vertical: 5), - decoration: BoxDecoration( - color: isSelected == true - ? AppColor.colorBackgroundWrapIconStyleCode - : Colors.white, - border: Border.all( - color: AppColor.colorBorderWrapIconStyleCode, - width: 0.5), - borderRadius: BorderRadius.circular(8)), - child: hasDropdown - ? Row( - mainAxisSize: MainAxisSize.min, - children: [ - icon, - if (spacing != null) SizedBox(width: spacing), - SvgPicture.asset(_imagePaths.icStyleArrowDown) - ]) - : icon, - ); - } - - if (onTap != null) { - return InkWell( - onTap: onTap, - child: buttonIcon, - ); - } else { - return buttonIcon; - } - } - - Widget buildIconStyleText({ - required String path, - required bool? isSelected, - required VoidCallback onTap, - String? tooltip, - double opacity = 1.0, - }){ - return buildIconWeb( - icon: SvgPicture.asset( - path, - colorFilter: isSelected == true - ? Colors.black.withValues(alpha: opacity).asFilter() - : AppColor.colorDefaultRichTextButton.withValues(alpha: opacity).asFilter(), - fit: BoxFit.fill), - iconPadding: const EdgeInsets.all(4), - colorFocus: Colors.white, - minSize: 26, - tooltip: tooltip, - onTap: onTap, - ); - } - - Widget buildIconWithTooltip({ - required String path, - Color? color, - String? tooltip, - double opacity = 1.0, - }){ - final newColor = color == Colors.white - ? AppColor.colorDefaultRichTextButton - : color; - - return tooltip?.isNotEmpty == true - ? Tooltip( - message: tooltip, - child: SvgPicture.asset( - path, - colorFilter: newColor?.withValues(alpha: opacity).asFilter(), - fit: BoxFit.fill)) - : SvgPicture.asset( - path, - colorFilter: newColor?.withValues(alpha: opacity).asFilter(), - fit: BoxFit.fill); - } - - Widget buildIconColorBackgroundText({ - required IconData? iconData, - required Color? colorSelected, - String? tooltip, - double opacity = 1.0, - }){ - final newColor = colorSelected == Colors.white - ? AppColor.colorDefaultRichTextButton - : colorSelected; - return Tooltip( - message: tooltip, - child: Icon(iconData, - color: (newColor ?? AppColor.colorDefaultRichTextButton).withValues(alpha: opacity), - size: 20), - ); - } -} \ 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 efd333ac7..17cb8cf4b 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 @@ -15,7 +15,7 @@ class BottomBarComposerWidgetStyle { static const Color backgroundColor = Colors.white; static const Color iconColor = AppColor.steelGrayA540; static const Color sendButtonBackgroundColor = AppColor.blue700; - static const Color selectedIconColor = AppColor.steelGrayA540; + static const Color selectedIconColor = AppColor.m3Primary; static const Color disabledIconColor = AppColor.colorRichButtonComposer; static const Color selectedBackgroundColor = AppColor.colorSelected; diff --git a/lib/features/composer/presentation/styles/web/dropdown_button_font_size_widget_style.dart b/lib/features/composer/presentation/styles/web/dropdown_button_font_size_widget_style.dart index 20391ab52..0fafb6d4a 100644 --- a/lib/features/composer/presentation/styles/web/dropdown_button_font_size_widget_style.dart +++ b/lib/features/composer/presentation/styles/web/dropdown_button_font_size_widget_style.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; class DropdownButtonFontSizeWidgetStyle { static const double borderWidth = 0.5; static const double radius = 8; - static const double height = 36; + static const double height = 40; static const double labelRadius = 4; static const double space = 4; diff --git a/lib/features/composer/presentation/styles/web/toolbar_rich_text_builder_style.dart b/lib/features/composer/presentation/styles/web/toolbar_rich_text_builder_style.dart index 38549de26..848c2b388 100644 --- a/lib/features/composer/presentation/styles/web/toolbar_rich_text_builder_style.dart +++ b/lib/features/composer/presentation/styles/web/toolbar_rich_text_builder_style.dart @@ -2,8 +2,14 @@ import 'package:flutter/material.dart'; class ToolbarRichTextBuilderStyle { - static const double itemHorizontalSpace = 8.0; static const double itemVerticalSpace = 8.0; - static const EdgeInsetsGeometry padding = EdgeInsetsDirectional.only(start: 20, top: 8, bottom: 8); + static const EdgeInsetsGeometry optionPadding = EdgeInsetsDirectional.only( + end: 8, + ); + static const EdgeInsetsGeometry padding = EdgeInsetsDirectional.only( + start: 20, + top: 8, + bottom: 8, + ); } \ No newline at end of file diff --git a/lib/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart b/lib/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart index 2bb6d340b..eae333f2e 100644 --- a/lib/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart +++ b/lib/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart @@ -29,45 +29,43 @@ class DropDownMenuHeaderStyleWidget extends StatelessWidget { @override Widget build(BuildContext context) { return DropdownButtonHideUnderline( - child: PointerInterceptor( - child: DropdownButton2( - isExpanded: true, - items: items - .map((item) => DropdownMenuItem( - value: item, - child: PointerInterceptor( - child: Container( - color: Colors.transparent, - height: heightItem, - alignment: Alignment.centerLeft, - child: _buildItemDropdown(item), - ), + child: DropdownButton2( + isExpanded: true, + items: items + .map((item) => DropdownMenuItem( + value: item, + child: PointerInterceptor( + child: Container( + color: Colors.transparent, + height: heightItem, + alignment: AlignmentDirectional.centerStart, + child: _buildItemDropdown(item), ), - )) - .toList(), - customButton: icon, - onChanged: onChanged, - onMenuStateChange: onMenuStateChange, - buttonStyleData: ButtonStyleData(height: heightItem), - dropdownStyleData: DropdownStyleData( - maxHeight: 200, - width: dropdownWidth, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: Colors.white), - elevation: 4, - offset: const Offset(0.0, -8.0), - scrollbarTheme: ScrollbarThemeData( - radius: const Radius.circular(40), - thickness: WidgetStateProperty.all(6), - thumbVisibility: WidgetStateProperty.all(true), - ) - ), - menuItemStyleData: MenuItemStyleData( - height: heightItem, - padding: const EdgeInsets.symmetric(horizontal: 12) + ), + )) + .toList(), + customButton: icon, + onChanged: onChanged, + onMenuStateChange: onMenuStateChange, + buttonStyleData: ButtonStyleData(height: heightItem), + dropdownStyleData: DropdownStyleData( + maxHeight: 200, + width: dropdownWidth, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Colors.white), + elevation: 4, + offset: const Offset(0.0, -8.0), + scrollbarTheme: ScrollbarThemeData( + radius: const Radius.circular(40), + thickness: WidgetStateProperty.all(6), + thumbVisibility: WidgetStateProperty.all(true), ) ), + menuItemStyleData: MenuItemStyleData( + height: heightItem, + padding: const EdgeInsets.symmetric(horizontal: 12) + ) ), ); } diff --git a/lib/features/composer/presentation/widgets/web/bottom_bar_composer_widget.dart b/lib/features/composer/presentation/widgets/web/bottom_bar_composer_widget.dart index 98e093dff..ca099be31 100644 --- a/lib/features/composer/presentation/widgets/web/bottom_bar_composer_widget.dart +++ b/lib/features/composer/presentation/widgets/web/bottom_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'; @@ -60,17 +61,24 @@ class BottomBarComposerWidget extends StatelessWidget { color: BottomBarComposerWidgetStyle.backgroundColor, child: Row( children: [ - TMailButtonWidget.fromIcon( - icon: imagePaths.icRichToolbar, - borderRadius: BottomBarComposerWidgetStyle.iconRadius, - padding: BottomBarComposerWidgetStyle.iconPadding, - backgroundColor: Colors.transparent, - iconSize: BottomBarComposerWidgetStyle.iconSize, - iconColor: isFormattingOptionsEnabled - ? BottomBarComposerWidgetStyle.selectedIconColor - : BottomBarComposerWidgetStyle.iconColor, - tooltipMessage: AppLocalizations.of(context).formattingOptions, - onTapActionCallback: openRichToolbarAction, + AbsorbPointer( + absorbing: isCodeViewEnabled, + child: TMailButtonWidget.fromIcon( + icon: imagePaths.icRichToolbar, + borderRadius: BottomBarComposerWidgetStyle.iconRadius, + padding: BottomBarComposerWidgetStyle.iconPadding, + backgroundColor: isFormattingOptionsEnabled + ? AppColor.m3Primary95 + : Colors.transparent, + iconSize: BottomBarComposerWidgetStyle.iconSize, + iconColor: isCodeViewEnabled + ? BottomBarComposerWidgetStyle.disabledIconColor + : isFormattingOptionsEnabled + ? BottomBarComposerWidgetStyle.selectedIconColor + : BottomBarComposerWidgetStyle.iconColor, + tooltipMessage: AppLocalizations.of(context).formattingOptions, + onTapActionCallback: openRichToolbarAction, + ), ), const SizedBox(width: BottomBarComposerWidgetStyle.space), TMailButtonWidget.fromIcon( diff --git a/lib/features/composer/presentation/widgets/web/dropdown_button_font_size_widget.dart b/lib/features/composer/presentation/widgets/web/dropdown_button_font_size_widget.dart index 6b1abf80a..aa13e2196 100644 --- a/lib/features/composer/presentation/widgets/web/dropdown_button_font_size_widget.dart +++ b/lib/features/composer/presentation/widgets/web/dropdown_button_font_size_widget.dart @@ -2,19 +2,18 @@ import 'package:core/presentation/resources/image_paths.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart'; import 'package:tmail_ui_user/features/composer/presentation/styles/web/dropdown_button_font_size_widget_style.dart'; class DropdownButtonFontSizeWidget extends StatelessWidget { - final _imagePaths = Get.find(); - + final ImagePaths imagePaths; final int value; - DropdownButtonFontSizeWidget({ + const DropdownButtonFontSizeWidget({ Key? key, required this.value, + required this.imagePaths, }) : super(key: key); @override @@ -51,7 +50,7 @@ class DropdownButtonFontSizeWidget extends StatelessWidget { ), ), const SizedBox(width: DropdownButtonFontSizeWidgetStyle.space), - SvgPicture.asset(_imagePaths.icStyleArrowDown) + SvgPicture.asset(imagePaths.icStyleArrowDown) ], ), ), diff --git a/lib/features/composer/presentation/widgets/web/dropdown_menu_font_size_widget.dart b/lib/features/composer/presentation/widgets/web/dropdown_menu_font_size_widget.dart index d3446bee6..7ce615716 100644 --- a/lib/features/composer/presentation/widgets/web/dropdown_menu_font_size_widget.dart +++ b/lib/features/composer/presentation/widgets/web/dropdown_menu_font_size_widget.dart @@ -1,4 +1,5 @@ +import 'package:core/presentation/resources/image_paths.dart'; import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart'; @@ -8,12 +9,14 @@ import 'package:tmail_ui_user/features/composer/presentation/widgets/web/item_me class DropdownMenuFontSizeWidget extends StatelessWidget { - final Function(int?)? onChanged; final int selectedFontSize; + final ImagePaths imagePaths; + final Function(int?)? onChanged; const DropdownMenuFontSizeWidget({ Key? key, required this.selectedFontSize, + required this.imagePaths, this.onChanged, }) : super(key: key); @@ -31,7 +34,10 @@ class DropdownMenuFontSizeWidget extends StatelessWidget { ) ); }).toList(), - customButton: DropdownButtonFontSizeWidget(value: selectedFontSize), + customButton: DropdownButtonFontSizeWidget( + value: selectedFontSize, + imagePaths: imagePaths, + ), onChanged: onChanged, dropdownStyleData: const DropdownStyleData( maxHeight: DropdownMenuFontSizeWidgetStyle.menuMaxHeight, 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 deleted file mode 100644 index b01198720..000000000 --- a/lib/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart +++ /dev/null @@ -1,301 +0,0 @@ -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'; -import 'package:pointer_interceptor/pointer_interceptor.dart'; -import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart'; -import 'package:tmail_ui_user/features/base/widget/popup_menu_overlay_widget.dart'; -import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart'; -import 'package:tmail_ui_user/features/composer/presentation/mixin/rich_text_button_mixin.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/dropdown_menu_font_status.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/font_name_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/header_style_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/order_list_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/paragraph_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/styles/web/toolbar_rich_text_builder_style.dart'; -import 'package:tmail_ui_user/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart'; -import 'package:tmail_ui_user/features/composer/presentation/widgets/web/dropdown_menu_font_size_widget.dart'; - -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 Decoration? decoration; - final bool isHorizontalArrange; - - ToolbarRichTextWebBuilder({ - Key? key, - required this.richTextWebController, - this.padding, - this.extendedOption, - this.decoration, - this.isHorizontalArrange = false, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Obx(() { - final codeViewEnabled = richTextWebController.codeViewEnabled; - final opacity = codeViewEnabled ? 0.5 : 1.0; - - final listAction = [ - if (extendedOption?.isNotEmpty == true) ...extendedOption!, - AbsorbPointer( - absorbing: codeViewEnabled, - child: DropDownMenuHeaderStyleWidget( - icon: buildWrapIconStyleText( - isSelected: richTextWebController.isMenuHeaderStyleOpen, - icon: SvgPicture.asset( - RichTextStyleType.headerStyle.getIcon(_imagePaths), - colorFilter: AppColor.colorDefaultRichTextButton - .withValues(alpha: opacity) - .asFilter(), - fit: BoxFit.fill, - ), - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), - tooltip: RichTextStyleType.headerStyle.getTooltipButton(context), - ), - items: HeaderStyleType.values, - onMenuStateChange: (isOpen) { - final newStatus = isOpen - ? DropdownMenuFontStatus.open - : DropdownMenuFontStatus.closed; - richTextWebController.menuHeaderStyleStatus.value = newStatus; - }, - onChanged: richTextWebController.applyHeaderStyle, - ), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: DropdownMenuFontSizeWidget( - onChanged: richTextWebController.applyNewFontSize, - selectedFontSize: richTextWebController.selectedFontSize.value, - ), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: SizedBox( - width: 130, - child: DropDownButtonWidget( - items: FontNameType.values, - itemSelected: richTextWebController.selectedFontName.value, - onChanged: (newFont) => - richTextWebController.applyNewFontStyle(newFont), - onMenuStateChange: (isOpen) { - final newStatus = isOpen - ? DropdownMenuFontStatus.open - : DropdownMenuFontStatus.closed; - richTextWebController.menuFontStatus.value = newStatus; - }, - heightItem: 40, - sizeIconChecked: 16, - radiusButton: 8, - opacity: opacity, - dropdownWidth: 200, - colorButton: richTextWebController.isMenuFontOpen - ? AppColor.colorBackgroundWrapIconStyleCode - : Colors.white, - iconArrowDown: SvgPicture.asset(_imagePaths.icStyleArrowDown), - tooltip: RichTextStyleType.fontName.getTooltipButton(context), - supportSelectionIcon: true, - ), - ), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: buildWrapIconStyleText( - icon: buildIconWithTooltip( - path: RichTextStyleType.textColor.getIcon(_imagePaths), - color: richTextWebController.selectedTextColor.value, - tooltip: RichTextStyleType.textColor.getTooltipButton(context), - opacity: opacity, - ), - onTap: () => richTextWebController.applyRichTextStyle( - context, - RichTextStyleType.textColor, - ), - ), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: buildWrapIconStyleText( - padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 7), - spacing: 3, - icon: buildIconColorBackgroundText( - iconData: RichTextStyleType.textBackgroundColor.getIconData(), - colorSelected: - richTextWebController.selectedTextBackgroundColor.value, - tooltip: RichTextStyleType.textBackgroundColor - .getTooltipButton(context), - opacity: opacity, - ), - onTap: () => richTextWebController.applyRichTextStyle( - context, - RichTextStyleType.textBackgroundColor, - ), - ), - ), - buildWrapIconStyleText( - hasDropdown: false, - padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 5), - icon: Wrap( - children: [ - AbsorbPointer( - absorbing: codeViewEnabled, - child: buildIconStyleText( - path: RichTextStyleType.bold.getIcon(_imagePaths), - isSelected: richTextWebController - .isTextStyleTypeSelected(RichTextStyleType.bold), - tooltip: RichTextStyleType.bold.getTooltipButton(context), - opacity: opacity, - onTap: () => richTextWebController.applyRichTextStyle( - context, - RichTextStyleType.bold, - ), - ), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: buildIconStyleText( - path: RichTextStyleType.italic.getIcon(_imagePaths), - isSelected: richTextWebController - .isTextStyleTypeSelected(RichTextStyleType.italic), - tooltip: RichTextStyleType.italic.getTooltipButton(context), - opacity: opacity, - onTap: () => richTextWebController.applyRichTextStyle( - context, - RichTextStyleType.italic, - ), - ), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: buildIconStyleText( - path: RichTextStyleType.underline.getIcon(_imagePaths), - isSelected: richTextWebController - .isTextStyleTypeSelected(RichTextStyleType.underline), - tooltip: - RichTextStyleType.underline.getTooltipButton(context), - opacity: opacity, - onTap: () => richTextWebController.applyRichTextStyle( - context, - RichTextStyleType.underline, - ), - ), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: buildIconStyleText( - path: RichTextStyleType.strikeThrough.getIcon(_imagePaths), - isSelected: richTextWebController - .isTextStyleTypeSelected(RichTextStyleType.strikeThrough), - tooltip: - RichTextStyleType.strikeThrough.getTooltipButton(context), - opacity: opacity, - onTap: () => richTextWebController.applyRichTextStyle( - context, - RichTextStyleType.strikeThrough, - ), - ), - ), - ], - ), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: PopupMenuOverlayWidget( - controller: richTextWebController.menuParagraphController, - listButtonAction: ParagraphType.values - .map((paragraph) => paragraph.buildButtonWidget( - context, - _imagePaths, - (paragraph) => - richTextWebController.applyParagraphType(paragraph))) - .toList(), - padding: const EdgeInsets.symmetric(horizontal: 5), - iconButton: buildWrapIconStyleText( - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), - spacing: 3, - isSelected: richTextWebController.focusMenuParagraph.value, - icon: buildIconWithTooltip( - path: richTextWebController.selectedParagraph.value - .getIcon(_imagePaths), - color: AppColor.colorDefaultRichTextButton, - opacity: opacity, - tooltip: RichTextStyleType.paragraph.getTooltipButton(context), - ), - ), - position: _responsiveUtils.isMobile(context) - ? PreferredPosition.top - : PreferredPosition.bottom, - ), - ), - AbsorbPointer( - absorbing: codeViewEnabled, - child: PopupMenuOverlayWidget( - controller: richTextWebController.menuOrderListController, - listButtonAction: OrderListType.values - .map((orderType) => orderType.buildButtonWidget( - context, - _imagePaths, - (orderType) => - richTextWebController.applyOrderListType(orderType))) - .toList(), - padding: const EdgeInsets.symmetric(horizontal: 5), - iconButton: buildWrapIconStyleText( - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), - spacing: 3, - isSelected: richTextWebController.focusMenuOrderList.value, - icon: buildIconWithTooltip( - path: richTextWebController.selectedOrderList.value - .getIcon(_imagePaths), - color: AppColor.colorDefaultRichTextButton, - opacity: opacity, - tooltip: RichTextStyleType.orderList.getTooltipButton(context), - ), - ), - position: _responsiveUtils.isMobile(context) - ? PreferredPosition.top - : PreferredPosition.bottom, - ), - ), - ]; - - Widget bodyWidget; - - if (isHorizontalArrange) { - bodyWidget = SingleChildScrollView( - scrollDirection: Axis.horizontal, - physics: const ClampingScrollPhysics(), - child: Row( - mainAxisSize: MainAxisSize.min, - children: listAction, - ), - ); - } else { - bodyWidget = Wrap( - crossAxisAlignment: WrapCrossAlignment.center, - runSpacing: ToolbarRichTextBuilderStyle.itemVerticalSpace, - spacing: ToolbarRichTextBuilderStyle.itemHorizontalSpace, - children: listAction, - ); - } - - return PointerInterceptor( - child: Container( - padding: padding ?? ToolbarRichTextBuilderStyle.padding, - decoration: decoration, - width: double.infinity, - child: bodyWidget, - ), - ); - }); - } -} \ No newline at end of file diff --git a/lib/features/composer/presentation/widgets/web/toolbar_rich_text_widget.dart b/lib/features/composer/presentation/widgets/web/toolbar_rich_text_widget.dart new file mode 100644 index 000000000..9e2e53353 --- /dev/null +++ b/lib/features/composer/presentation/widgets/web/toolbar_rich_text_widget.dart @@ -0,0 +1,335 @@ +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:custom_pop_up_menu/custom_pop_up_menu.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/base/widget/arrow_down_icon_border_button_widget.dart'; +import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart'; +import 'package:tmail_ui_user/features/base/widget/popup_menu_overlay_widget.dart'; +import 'package:tmail_ui_user/features/base/widget/scrollbar_list_view.dart'; +import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/dropdown_menu_font_status.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/font_name_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/header_style_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/order_list_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/paragraph_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart'; +import 'package:tmail_ui_user/features/composer/presentation/styles/web/toolbar_rich_text_builder_style.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/web/dropdown_menu_font_size_widget.dart'; + +class ToolbarRichTextWidget extends StatelessWidget { + final RichTextWebController richTextController; + final ImagePaths imagePaths; + final bool isMobile; + final bool isHorizontalArrange; + final EdgeInsetsGeometry? padding; + final List? extendedOption; + final Decoration? decoration; + final ScrollController? scrollListController; + + const ToolbarRichTextWidget({ + Key? key, + required this.richTextController, + required this.imagePaths, + this.isMobile = false, + this.isHorizontalArrange = false, + this.padding, + this.extendedOption, + this.decoration, + this.scrollListController, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final textColorOption = Obx( + () { + final textColor = richTextController.selectedTextColor.value; + + return ArrowDownIconBorderButtonWidget( + imagePaths: imagePaths, + icon: RichTextStyleType.textColor.getIcon(imagePaths), + iconColor: textColor.toInt() == Colors.white.toInt() || + textColor.toInt() == 0 + ? AppColor.colorDefaultRichTextButton + : textColor, + tooltipMessage: RichTextStyleType.textColor.getTooltipButton( + context, + ), + height: 40, + padding: ToolbarRichTextBuilderStyle.optionPadding, + onTap: () => richTextController.applyRichTextStyle( + context, + RichTextStyleType.textColor, + ), + ); + }, + ); + + final backgroundColorOption = Obx( + () { + final backgroundColor = + richTextController.selectedTextBackgroundColor.value; + + return ArrowDownIconBorderButtonWidget( + imagePaths: imagePaths, + iconData: RichTextStyleType.textBackgroundColor.getIconData(), + iconColor: backgroundColor.toInt() == Colors.white.toInt() || + backgroundColor.toInt() == 0 + ? AppColor.colorDefaultRichTextButton + : backgroundColor, + tooltipMessage: + RichTextStyleType.textBackgroundColor.getTooltipButton( + context, + ), + height: 40, + padding: ToolbarRichTextBuilderStyle.optionPadding, + onTap: () => richTextController.applyRichTextStyle( + context, + RichTextStyleType.textBackgroundColor, + ), + ); + }, + ); + + final styleOption = Container( + margin: ToolbarRichTextBuilderStyle.optionPadding, + decoration: BoxDecoration( + border: Border.all( + color: AppColor.m3Neutral90, + ), + borderRadius: const BorderRadius.all(Radius.circular(8)), + ), + height: 40, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + RichTextStyleType.bold, + RichTextStyleType.italic, + RichTextStyleType.underline, + RichTextStyleType.strikeThrough, + ].map((style) { + return Obx( + () { + final isSelected = + richTextController.isTextStyleTypeSelected(style); + + return TMailButtonWidget.fromIcon( + icon: style.getIcon(imagePaths), + iconColor: isSelected ? Colors.black : AppColor.gray99A2AD, + backgroundColor: Colors.transparent, + padding: const EdgeInsets.all(5), + tooltipMessage: style.getTooltipButton(context), + onTapActionCallback: () => + richTextController.applyRichTextStyle(context, style), + ); + }, + ); + }).toList(), + ), + ); + + final paragraphOption = Padding( + padding: ToolbarRichTextBuilderStyle.optionPadding, + child: PopupMenuOverlayWidget( + controller: richTextController.menuParagraphController, + listButtonAction: ParagraphType.values.map((paragraph) { + return paragraph.buildButtonWidget( + context, + imagePaths, + richTextController.applyParagraphType, + ); + }).toList(), + padding: const EdgeInsets.symmetric(horizontal: 5), + position: isMobile ? PreferredPosition.top : PreferredPosition.bottom, + iconButton: Obx( + () { + return ArrowDownIconBorderButtonWidget( + imagePaths: imagePaths, + icon: richTextController.selectedParagraph.value + .getIcon(imagePaths), + backgroundColor: richTextController.focusMenuParagraph.isTrue + ? AppColor.colorBackgroundWrapIconStyleCode + : null, + iconColor: AppColor.colorDefaultRichTextButton, + height: 40, + tooltipMessage: + RichTextStyleType.paragraph.getTooltipButton(context), + ); + }, + ), + ), + ); + + final orderListOption = Padding( + padding: ToolbarRichTextBuilderStyle.optionPadding, + child: PopupMenuOverlayWidget( + controller: richTextController.menuOrderListController, + listButtonAction: OrderListType.values.map((orderType) { + return orderType.buildButtonWidget( + context, + imagePaths, + richTextController.applyOrderListType, + ); + }).toList(), + padding: const EdgeInsets.symmetric(horizontal: 5), + position: isMobile ? PreferredPosition.top : PreferredPosition.bottom, + iconButton: Obx( + () { + return ArrowDownIconBorderButtonWidget( + imagePaths: imagePaths, + icon: richTextController.selectedOrderList.value + .getIcon(imagePaths), + backgroundColor: richTextController.focusMenuOrderList.isTrue + ? AppColor.colorBackgroundWrapIconStyleCode + : null, + iconColor: AppColor.colorDefaultRichTextButton, + height: 40, + tooltipMessage: + RichTextStyleType.orderList.getTooltipButton(context), + ); + }, + ), + ), + ); + + final listOptions = [ + if (extendedOption?.isNotEmpty == true) ...extendedOption!, + Padding( + padding: ToolbarRichTextBuilderStyle.optionPadding, + child: DropDownMenuHeaderStyleWidget( + icon: Obx( + () { + return ArrowDownIconBorderButtonWidget( + imagePaths: imagePaths, + icon: RichTextStyleType.headerStyle.getIcon(imagePaths), + iconColor: AppColor.colorDefaultRichTextButton, + backgroundColor: richTextController.isMenuHeaderStyleOpen + ? AppColor.colorBackgroundWrapIconStyleCode + : null, + height: 40, + tooltipMessage: + RichTextStyleType.headerStyle.getTooltipButton(context), + ); + }, + ), + items: HeaderStyleType.values, + onMenuStateChange: (isOpen) { + final newStatus = isOpen + ? DropdownMenuFontStatus.open + : DropdownMenuFontStatus.closed; + richTextController.menuHeaderStyleStatus.value = newStatus; + }, + onChanged: richTextController.applyHeaderStyle, + ), + ), + Obx( + () { + return Padding( + padding: ToolbarRichTextBuilderStyle.optionPadding, + child: DropdownMenuFontSizeWidget( + selectedFontSize: richTextController.selectedFontSize.value, + imagePaths: imagePaths, + onChanged: richTextController.applyNewFontSize, + ), + ); + }, + ), + Container( + width: 130, + padding: ToolbarRichTextBuilderStyle.optionPadding, + child: Obx( + () { + return DropDownButtonWidget( + items: FontNameType.values, + itemSelected: richTextController.selectedFontName.value, + onChanged: richTextController.applyNewFontStyle, + onMenuStateChange: (isOpen) { + final newStatus = isOpen + ? DropdownMenuFontStatus.open + : DropdownMenuFontStatus.closed; + richTextController.menuFontStatus.value = newStatus; + }, + heightItem: 40, + sizeIconChecked: 16, + radiusButton: 8, + dropdownWidth: 200, + colorButton: richTextController.isMenuFontOpen + ? AppColor.colorBackgroundWrapIconStyleCode + : Colors.white, + iconArrowDown: SvgPicture.asset(imagePaths.icStyleArrowDown), + tooltip: RichTextStyleType.fontName.getTooltipButton(context), + supportSelectionIcon: true, + ); + }, + ), + ), + if (isHorizontalArrange) + Center(child: textColorOption) + else + textColorOption, + if (isHorizontalArrange) + Center(child: backgroundColorOption) + else + backgroundColorOption, + if (isHorizontalArrange) Center(child: styleOption) else styleOption, + if (isHorizontalArrange) + Center(child: paragraphOption) + else + paragraphOption, + if (isHorizontalArrange) + Center(child: orderListOption) + else + orderListOption, + ]; + + if (isHorizontalArrange) { + Widget listViewOption = ListView( + shrinkWrap: true, + scrollDirection: Axis.horizontal, + controller: scrollListController, + padding: const EdgeInsets.only(bottom: 8), + children: listOptions, + ); + + if (scrollListController != null) { + listViewOption = ScrollbarListView( + scrollBehavior: ScrollConfiguration.of(context).copyWith( + physics: const BouncingScrollPhysics(), + dragDevices: { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + PointerDeviceKind.trackpad, + }, + scrollbars: false, + ), + scrollController: scrollListController!, + child: listViewOption, + ); + } + + return Container( + alignment: AlignmentDirectional.bottomCenter, + padding: padding, + decoration: decoration, + height: 50, + child: listViewOption, + ); + } else { + return Container( + padding: padding ?? ToolbarRichTextBuilderStyle.padding, + decoration: decoration, + width: double.infinity, + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + runSpacing: ToolbarRichTextBuilderStyle.itemVerticalSpace, + spacing: 0.0, + children: listOptions, + ), + ); + } + } +} diff --git a/lib/features/identity_creator/presentation/identity_creator_view.dart b/lib/features/identity_creator/presentation/identity_creator_view.dart index b9c0a7739..96c8d68ec 100644 --- a/lib/features/identity_creator/presentation/identity_creator_view.dart +++ b/lib/features/identity_creator/presentation/identity_creator_view.dart @@ -16,7 +16,6 @@ import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:tmail_ui_user/features/base/widget/default_field/default_email_address_drop_down_button.dart'; import 'package:tmail_ui_user/features/base/widget/default_field/default_horizontal_field_widget.dart'; import 'package:tmail_ui_user/features/base/widget/default_field/default_label_field_widget.dart'; -import 'package:tmail_ui_user/features/composer/presentation/mixin/rich_text_button_mixin.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_controller.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/identity_creator_form_desktop_builder.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/identity_creator_form_mobile_builder.dart'; @@ -25,8 +24,7 @@ import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/ide import 'package:tmail_ui_user/features/manage_account/presentation/model/identity_action_type.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -class IdentityCreatorView extends GetWidget - with RichTextButtonMixin { +class IdentityCreatorView extends GetWidget { @override final controller = Get.find(); diff --git a/lib/features/identity_creator/presentation/widgets/identity_signature_input_field_widget.dart b/lib/features/identity_creator/presentation/widgets/identity_signature_input_field_widget.dart index ca0c8e1d6..cf1745701 100644 --- a/lib/features/identity_creator/presentation/widgets/identity_signature_input_field_widget.dart +++ b/lib/features/identity_creator/presentation/widgets/identity_signature_input_field_widget.dart @@ -1,6 +1,7 @@ import 'package:core/presentation/constants/constants_ui.dart'; import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/utils/html/html_template.dart'; +import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/utils/html/html_utils.dart'; import 'package:core/utils/platform_info.dart'; import 'package:flutter/material.dart'; @@ -8,20 +9,19 @@ import 'package:get/get.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:rich_text_composer/rich_text_composer.dart'; import 'package:html_editor_enhanced/html_editor.dart' as html_editor_browser; -import 'package:tmail_ui_user/features/composer/presentation/mixin/rich_text_button_mixin.dart'; +import 'package:tmail_ui_user/features/composer/presentation/styles/web/toolbar_rich_text_builder_style.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/web/local_file_drop_zone_widget.dart'; -import 'package:tmail_ui_user/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/web/toolbar_rich_text_widget.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_controller.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/widgets/insert_image_loading_indicator.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/draggable_app_state.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/utils/app_utils.dart'; -class IdentitySignatureInputFieldWidget extends StatelessWidget - with RichTextButtonMixin { +class IdentitySignatureInputFieldWidget extends StatelessWidget { final IdentityCreatorController controller; - IdentitySignatureInputFieldWidget({ + const IdentitySignatureInputFieldWidget({ super.key, required this.controller, }); @@ -91,19 +91,27 @@ class IdentitySignatureInputFieldWidget extends StatelessWidget return Column( mainAxisSize: MainAxisSize.min, children: [ - ToolbarRichTextWebBuilder( - richTextWebController: controller.richTextWebController!, + ToolbarRichTextWidget( + richTextController: controller.richTextWebController!, + imagePaths: controller.imagePaths, padding: const EdgeInsets.only(bottom: 12), + isMobile: controller.responsiveUtils.isMobile(context), extendedOption: [ - Padding( - padding: const EdgeInsetsDirectional.only(end: 4.0), - child: buildWrapIconStyleText( - icon: buildIconWithTooltip( - path: controller.imagePaths.icAddPicture, - tooltip: AppLocalizations.of(context).insertImage, + Container( + margin: ToolbarRichTextBuilderStyle.optionPadding, + decoration: BoxDecoration( + border: Border.all( + color: AppColor.m3Neutral90, ), - hasDropdown: false, - onTap: () => controller.pickImage(context), + borderRadius: const BorderRadius.all(Radius.circular(8)), + ), + height: 40, + child: TMailButtonWidget.fromIcon( + icon: controller.imagePaths.icAddPicture, + padding: const EdgeInsets.all(5), + backgroundColor: Colors.transparent, + tooltipMessage: AppLocalizations.of(context).insertImage, + onTapActionCallback: () => controller.pickImage(context), ), ), ], diff --git a/lib/features/manage_account/presentation/vacation/vacation_view.dart b/lib/features/manage_account/presentation/vacation/vacation_view.dart index 2c40449bc..79137be93 100644 --- a/lib/features/manage_account/presentation/vacation/vacation_view.dart +++ b/lib/features/manage_account/presentation/vacation/vacation_view.dart @@ -17,13 +17,13 @@ import 'package:rich_text_composer/views/widgets/rich_text_keyboard_toolbar.dart import 'package:tmail_ui_user/features/base/widget/label_border_button_field.dart'; import 'package:tmail_ui_user/features/base/widget/switch_label_button_widget.dart'; import 'package:tmail_ui_user/features/base/widget/label_input_field_builder.dart'; +import 'package:tmail_ui_user/features/composer/presentation/widgets/web/toolbar_rich_text_widget.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/base/setting_detail_view_builder.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings_utils.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/vacation/date_type.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/vacation/vacation_responder_status.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_controller.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/horizontal_toolbar_rich_text_widget.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_list_action_widget.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/widgets/setting_explanation_widget.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/widgets/setting_header_widget.dart'; @@ -36,7 +36,7 @@ class VacationView extends GetWidget { @override Widget build(BuildContext context) { - Widget vacationInputForm = SingleChildScrollView( + final vacationInputForm = SingleChildScrollView( physics: const ClampingScrollPhysics(), controller: controller.scrollController, child: Padding( @@ -400,10 +400,12 @@ class VacationView extends GetWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Flexible(child: _buildMessageHtmlTextEditor(context)), - HorizontalToolbarRichTextWidget( + ToolbarRichTextWidget( richTextController: controller.richTextControllerForWeb!, - scrollController: controller.richTextButtonScrollController, + scrollListController: controller.richTextButtonScrollController, imagePaths: controller.imagePaths, + isHorizontalArrange: true, + isMobile: controller.responsiveUtils.isMobile(context), ), ], ), @@ -444,10 +446,12 @@ class VacationView extends GetWidget { children: [ Flexible(child: _buildMessageHtmlTextEditor(context)), const SizedBox(height: 8), - HorizontalToolbarRichTextWidget( + ToolbarRichTextWidget( richTextController: controller.richTextControllerForWeb!, - scrollController: controller.richTextButtonScrollController, + scrollListController: controller.richTextButtonScrollController, imagePaths: controller.imagePaths, + isHorizontalArrange: true, + isMobile: controller.responsiveUtils.isMobile(context), ), ], ), diff --git a/lib/features/manage_account/presentation/vacation/widgets/horizontal_toolbar_rich_text_widget.dart b/lib/features/manage_account/presentation/vacation/widgets/horizontal_toolbar_rich_text_widget.dart deleted file mode 100644 index 22ecb12b7..000000000 --- a/lib/features/manage_account/presentation/vacation/widgets/horizontal_toolbar_rich_text_widget.dart +++ /dev/null @@ -1,269 +0,0 @@ -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:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; -import 'package:tmail_ui_user/features/base/widget/arrow_down_icon_border_button_widget.dart'; -import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart'; -import 'package:tmail_ui_user/features/base/widget/popup_menu_overlay_widget.dart'; -import 'package:tmail_ui_user/features/base/widget/scrollbar_list_view.dart'; -import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/dropdown_menu_font_status.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/font_name_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/header_style_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/order_list_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/paragraph_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart'; -import 'package:tmail_ui_user/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart'; - -class HorizontalToolbarRichTextWidget extends StatelessWidget { - final RichTextWebController richTextController; - final ScrollController scrollController; - final ImagePaths imagePaths; - - const HorizontalToolbarRichTextWidget({ - super.key, - required this.richTextController, - required this.scrollController, - required this.imagePaths, - }); - - @override - Widget build(BuildContext context) { - return Container( - alignment: AlignmentDirectional.bottomCenter, - height: 50, - child: ScrollbarListView( - scrollBehavior: ScrollConfiguration.of(context).copyWith( - physics: const BouncingScrollPhysics(), - dragDevices: { - PointerDeviceKind.touch, - PointerDeviceKind.mouse, - PointerDeviceKind.trackpad, - }, - scrollbars: false, - ), - scrollController: scrollController, - child: ListView( - shrinkWrap: true, - scrollDirection: Axis.horizontal, - controller: scrollController, - padding: const EdgeInsets.only(bottom: 8), - children: [ - DropDownMenuHeaderStyleWidget( - icon: Obx( - () { - return ArrowDownIconBorderButtonWidget( - imagePaths: imagePaths, - icon: RichTextStyleType.headerStyle.getIcon(imagePaths), - iconColor: AppColor.colorDefaultRichTextButton, - backgroundColor: richTextController.isMenuHeaderStyleOpen - ? AppColor.colorBackgroundWrapIconStyleCode - : null, - tooltipMessage: - RichTextStyleType.headerStyle.getTooltipButton(context), - ); - }, - ), - items: HeaderStyleType.values, - onMenuStateChange: (isOpen) { - final newStatus = isOpen - ? DropdownMenuFontStatus.open - : DropdownMenuFontStatus.closed; - richTextController.menuHeaderStyleStatus.value = newStatus; - }, - onChanged: richTextController.applyHeaderStyle, - ), - Container( - width: 130, - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Obx( - () { - return DropDownButtonWidget( - items: FontNameType.values, - itemSelected: richTextController.selectedFontName.value, - onChanged: richTextController.applyNewFontStyle, - onMenuStateChange: (isOpen) { - final newStatus = isOpen - ? DropdownMenuFontStatus.open - : DropdownMenuFontStatus.closed; - richTextController.menuFontStatus.value = newStatus; - }, - heightItem: 40, - sizeIconChecked: 16, - radiusButton: 8, - dropdownWidth: 200, - colorButton: richTextController.isMenuFontOpen - ? AppColor.colorBackgroundWrapIconStyleCode - : Colors.white, - iconArrowDown: SvgPicture.asset(imagePaths.icStyleArrowDown), - tooltip: RichTextStyleType.fontName.getTooltipButton(context), - supportSelectionIcon: true, - ); - }, - ), - ), - Center( - child: Obx( - () { - final textColor = richTextController - .selectedTextColor - .value; - - return ArrowDownIconBorderButtonWidget( - imagePaths: imagePaths, - icon: RichTextStyleType.textColor.getIcon(imagePaths), - iconColor: textColor.toInt() == Colors.white.toInt() || - textColor.toInt() == 0 - ? AppColor.colorDefaultRichTextButton - : textColor, - tooltipMessage: RichTextStyleType.textColor.getTooltipButton( - context, - ), - height: 40, - padding: const EdgeInsetsDirectional.only(end: 4.0), - onTap: () => richTextController.applyRichTextStyle( - context, - RichTextStyleType.textColor, - ), - ); - }, - ), - ), - Center( - child: Obx( - () { - final backgroundColor = richTextController - .selectedTextBackgroundColor - .value; - - return ArrowDownIconBorderButtonWidget( - imagePaths: imagePaths, - iconData: RichTextStyleType.textBackgroundColor.getIconData(), - iconColor: backgroundColor.toInt() == Colors.white.toInt() - || backgroundColor.toInt() == 0 - ? AppColor.colorDefaultRichTextButton - : backgroundColor, - tooltipMessage: RichTextStyleType.textBackgroundColor.getTooltipButton( - context, - ), - height: 40, - padding: const EdgeInsetsDirectional.only(end: 4.0), - onTap: () => richTextController.applyRichTextStyle( - context, - RichTextStyleType.textBackgroundColor, - ), - ); - }, - ), - ), - Center( - child: Container( - margin: const EdgeInsetsDirectional.only(end: 4.0), - decoration: BoxDecoration( - border: Border.all( - color: AppColor.m3Neutral90, - ), - borderRadius: const BorderRadius.all(Radius.circular(8)), - ), - height: 40, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - RichTextStyleType.bold, - RichTextStyleType.italic, - RichTextStyleType.underline, - RichTextStyleType.strikeThrough, - ].map((style) { - return Obx( - () { - final isSelected = richTextController - .isTextStyleTypeSelected(style); - - return TMailButtonWidget.fromIcon( - icon: style.getIcon(imagePaths), - iconColor: isSelected - ? Colors.black - : AppColor.gray99A2AD, - backgroundColor: Colors.transparent, - padding: const EdgeInsets.all(5), - tooltipMessage: style.getTooltipButton(context), - onTapActionCallback: () => - richTextController.applyRichTextStyle(context, style), - ); - }, - ); - }).toList(), - ), - ), - ), - Center( - child: Padding( - padding: const EdgeInsetsDirectional.only(end: 4.0), - child: PopupMenuOverlayWidget( - controller: richTextController.menuParagraphController, - listButtonAction: ParagraphType.values.map((paragraph) { - return paragraph.buildButtonWidget( - context, - imagePaths, - richTextController.applyParagraphType, - ); - }).toList(), - padding: const EdgeInsets.symmetric(horizontal: 5), - iconButton: Obx( - () { - return ArrowDownIconBorderButtonWidget( - imagePaths: imagePaths, - icon: richTextController.selectedParagraph.value - .getIcon(imagePaths), - backgroundColor: richTextController.focusMenuParagraph.isTrue - ? AppColor.colorBackgroundWrapIconStyleCode - : null, - iconColor: AppColor.colorDefaultRichTextButton, - tooltipMessage: - RichTextStyleType.paragraph.getTooltipButton(context), - ); - }, - ), - ), - ), - ), - Center( - child: Padding( - padding: const EdgeInsetsDirectional.only(end: 4.0), - child: PopupMenuOverlayWidget( - controller: richTextController.menuOrderListController, - listButtonAction: OrderListType.values.map((orderType) { - return orderType.buildButtonWidget( - context, - imagePaths, - richTextController.applyOrderListType, - ); - }).toList(), - padding: const EdgeInsets.symmetric(horizontal: 5), - iconButton: Obx( - () { - return ArrowDownIconBorderButtonWidget( - imagePaths: imagePaths, - icon: richTextController.selectedOrderList.value - .getIcon(imagePaths), - backgroundColor: richTextController.focusMenuOrderList.isTrue - ? AppColor.colorBackgroundWrapIconStyleCode - : null, - iconColor: AppColor.colorDefaultRichTextButton, - tooltipMessage: - RichTextStyleType.orderList.getTooltipButton(context), - ); - }, - ), - ), - ), - ), - ], - ), - ), - ); - } -}