TF-3956 Add font size in toolbar of vacation editor

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-08-18 11:34:20 +07:00
committed by Dat H. Pham
parent ff66953c78
commit 5423a9096c
17 changed files with 466 additions and 802 deletions
@@ -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)],
@@ -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<ComposerController> {
@@ -268,13 +268,15 @@ class ComposerView extends GetWidget<ComposerController> {
}),
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<ComposerController> {
}),
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<ComposerController> {
}),
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();
@@ -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) {
@@ -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<ImagePaths>();
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),
);
}
}
@@ -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;
@@ -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;
@@ -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,
);
}
@@ -29,45 +29,43 @@ class DropDownMenuHeaderStyleWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DropdownButtonHideUnderline(
child: PointerInterceptor(
child: DropdownButton2<HeaderStyleType>(
isExpanded: true,
items: items
.map((item) => DropdownMenuItem<HeaderStyleType>(
value: item,
child: PointerInterceptor(
child: Container(
color: Colors.transparent,
height: heightItem,
alignment: Alignment.centerLeft,
child: _buildItemDropdown(item),
),
child: DropdownButton2<HeaderStyleType>(
isExpanded: true,
items: items
.map((item) => DropdownMenuItem<HeaderStyleType>(
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<double>(6),
thumbVisibility: WidgetStateProperty.all<bool>(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<double>(6),
thumbVisibility: WidgetStateProperty.all<bool>(true),
)
),
menuItemStyleData: MenuItemStyleData(
height: heightItem,
padding: const EdgeInsets.symmetric(horizontal: 12)
)
),
);
}
@@ -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(
@@ -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<ImagePaths>();
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)
],
),
),
@@ -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,
@@ -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<ImagePaths>();
final ResponsiveUtils _responsiveUtils = Get.find<ResponsiveUtils>();
final EdgeInsetsGeometry? padding;
final List<Widget>? 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<FontNameType>(
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,
),
);
});
}
}
@@ -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<Widget>? 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>[
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 = <Widget>[
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<FontNameType>(
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,
),
);
}
}
}
@@ -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<IdentityCreatorController>
with RichTextButtonMixin {
class IdentityCreatorView extends GetWidget<IdentityCreatorController> {
@override
final controller = Get.find<IdentityCreatorController>();
@@ -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),
),
),
],
@@ -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<VacationController> {
@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<VacationController> {
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<VacationController> {
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),
),
],
),
@@ -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<FontNameType>(
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>[
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),
);
},
),
),
),
),
],
),
),
);
}
}