diff --git a/lib/features/base/widget/drop_down_button_widget.dart b/lib/features/base/widget/drop_down_button_widget.dart index c158ad3ae..07ad6bc57 100644 --- a/lib/features/base/widget/drop_down_button_widget.dart +++ b/lib/features/base/widget/drop_down_button_widget.dart @@ -3,6 +3,7 @@ import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/utils/style_utils.dart'; import 'package:dropdown_button2/dropdown_button2.dart'; +import 'package:enough_html_editor/enough_html_editor.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; @@ -156,6 +157,9 @@ class DropDownButtonWidget extends StatelessWidget { if (item is FontNameType) { return item.fontFamily; } + if (item is SafeFont) { + return item.name; + } return ''; } } \ No newline at end of file diff --git a/lib/features/composer/presentation/composer_view.dart b/lib/features/composer/presentation/composer_view.dart index 3d8649b0f..580197e0d 100644 --- a/lib/features/composer/presentation/composer_view.dart +++ b/lib/features/composer/presentation/composer_view.dart @@ -10,8 +10,10 @@ import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart'; +import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_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/rich_text_style_type.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_file_composer_builder.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart'; @@ -460,10 +462,7 @@ class ComposerView extends GetWidget with AppLoaderMixin, Ri Padding( padding: const EdgeInsets.only(left: 60, right: 25), child: Column(children: [ - Padding( - padding: const EdgeInsets.only(left: 22, top: 15), - child: Obx(() => _buildRowIconStyleText()), - ), + _buildToolbarRichTextWidget(context), const SizedBox(height: 8), Obx(() { final uploadAttachments = controller.uploadController.listUploadAttachments; @@ -493,46 +492,55 @@ class ComposerView extends GetWidget with AppLoaderMixin, Ri ); } - Widget _buildRowIconStyleText() { - return Row( - children: [ - buildIconStyleText( - path: RichTextStyleType.bold.getIcon(imagePaths), - isSelected: controller.richTextMobileTabletController.isTextStyleTypeSelected(RichTextStyleType.bold), - onTap: () async { - await controller.htmlEditorApi?.formatBold().then((value) { - controller.richTextMobileTabletController.selectTextStyleType(RichTextStyleType.bold); - }); + Widget _buildToolbarRichTextWidget(BuildContext context) { + return Container( + padding: const EdgeInsets.only(left: 20, top: 15, bottom: 8), + alignment: Alignment.centerLeft, + child: Wrap( + alignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, + children: RichTextStyleType.values.map((textType) => Obx(() { + switch(textType) { + case RichTextStyleType.textColor: + return buildIconColorText( + iconData: textType.getIconData(), + colorSelected: controller.richTextMobileTabletController.selectedTextColor.value, + onTap: () => controller.richTextMobileTabletController.applyRichTextStyle(context, textType)); + case RichTextStyleType.textBackgroundColor: + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 2), + child: buildIconColorBackgroundText( + iconData: textType.getIconData(), + colorSelected: controller.richTextMobileTabletController.selectedTextBackgroundColor.value, + tooltip: textType.getTooltipButton(context), + onTap: () => controller.richTextMobileTabletController.applyRichTextStyle(context, textType)), + ); + case RichTextStyleType.fontName: + return Container( + width: 200, + padding: const EdgeInsets.only(right: 2), + child: DropDownButtonWidget( + items: SafeFont.values, + itemSelected: controller.richTextMobileTabletController.selectedFontName.value, + onChanged: (newFont) => controller.richTextMobileTabletController.applyNewFontStyle(newFont), + onMenuStateChange: (isOpen) { + final newStatus = isOpen + ? DropdownMenuFontStatus.open + : DropdownMenuFontStatus.closed; + controller.richTextMobileTabletController.menuFontStatus = newStatus; + }, + heightItem: 35, + sizeIconChecked: 16, + radiusButton: 5, + supportSelectionIcon: true)); + default: + return buildIconStyleText( + path: textType.getIcon(imagePaths), + isSelected: controller.richTextMobileTabletController.isTextStyleTypeSelected(textType), + onTap: () => controller.richTextMobileTabletController.applyRichTextStyle(context, textType)); } - ), - buildIconStyleText( - path: RichTextStyleType.italic.getIcon(imagePaths), - isSelected: controller.richTextMobileTabletController.isTextStyleTypeSelected(RichTextStyleType.italic), - onTap: () async { - await controller.htmlEditorApi?.formatItalic().then((value) { - controller.richTextMobileTabletController.selectTextStyleType(RichTextStyleType.italic); - }); - } - ), - buildIconStyleText( - path: RichTextStyleType.strikeThrough.getIcon(imagePaths), - isSelected: controller.richTextMobileTabletController.isTextStyleTypeSelected(RichTextStyleType.strikeThrough), - onTap: () async { - await controller.htmlEditorApi?.formatStrikeThrough().then((value) { - controller.richTextMobileTabletController.selectTextStyleType(RichTextStyleType.strikeThrough); - }); - } - ), - buildIconStyleText( - path: RichTextStyleType.underline.getIcon(imagePaths), - isSelected: controller.richTextMobileTabletController.isTextStyleTypeSelected(RichTextStyleType.underline), - onTap: () async { - await controller.htmlEditorApi?.formatUnderline().then((value) { - controller.richTextMobileTabletController.selectTextStyleType(RichTextStyleType.underline); - }); - } - ), - ], + })).toList() + ), ); } diff --git a/lib/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart b/lib/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart index 31dcabb81..1b9e732cf 100644 --- a/lib/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart +++ b/lib/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart @@ -1,10 +1,19 @@ import 'package:enough_html_editor/enough_html_editor.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/composer/presentation/controller/base_rich_text_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/rich_text_style_type.dart'; +import 'package:tmail_ui_user/main/routes/route_navigation.dart'; -class RichTextMobileTabletController extends GetxController { +class RichTextMobileTabletController extends BaseRichTextController { HtmlEditorApi? htmlEditorApi; final listTextStyleApply = RxList(); + final selectedTextColor = Colors.black.obs; + final selectedTextBackgroundColor = Colors.white.obs; + final selectedFontName = SafeFont.sansSerif.obs; + + DropdownMenuFontStatus menuFontStatus = DropdownMenuFontStatus.closed; void listenHtmlEditorApi() { htmlEditorApi?.onFormatSettingsChanged = (formatSettings) { @@ -27,7 +36,57 @@ class RichTextMobileTabletController extends GetxController { }; } - selectTextStyleType(RichTextStyleType richTextStyleType) { + void applyRichTextStyle( + BuildContext context, RichTextStyleType textStyleType) async { + switch (textStyleType) { + case RichTextStyleType.textColor: + openMenuSelectColor(context, selectedTextColor.value, + onResetToDefault: () { + selectedTextColor.value = Colors.black; + htmlEditorApi?.setColorDocumentForeground(selectedTextColor.value); + }, onSelectColor: (selectedColor) { + final newColor = selectedColor ?? Colors.black; + selectedTextColor.value = newColor; + htmlEditorApi?.setColorTextForeground(selectedTextColor.value); + }); + break; + case RichTextStyleType.textBackgroundColor: + openMenuSelectColor(context, selectedTextBackgroundColor.value, + onResetToDefault: () { + selectedTextBackgroundColor.value = Colors.white; + htmlEditorApi?.setColorTextBackground(selectedTextBackgroundColor.value); + }, onSelectColor: (selectedColor) { + final newColor = selectedColor ?? Colors.white; + selectedTextBackgroundColor.value = newColor; + htmlEditorApi?.setColorTextBackground(selectedTextBackgroundColor.value); + }); + break; + case RichTextStyleType.bold: + await htmlEditorApi?.formatBold().then((value) { + _selectTextStyleType(RichTextStyleType.bold); + }); + break; + case RichTextStyleType.italic: + await htmlEditorApi?.formatItalic().then((value) { + _selectTextStyleType(RichTextStyleType.italic); + }); + break; + case RichTextStyleType.underline: + await htmlEditorApi?.formatUnderline().then((value) { + _selectTextStyleType(RichTextStyleType.underline); + }); + break; + case RichTextStyleType.strikeThrough: + await htmlEditorApi?.formatStrikeThrough().then((value) { + _selectTextStyleType(RichTextStyleType.strikeThrough); + }); + break; + default: + break; + } + } + + _selectTextStyleType(RichTextStyleType richTextStyleType) { if (listTextStyleApply.contains(richTextStyleType)) { listTextStyleApply.remove(richTextStyleType); } else { @@ -38,4 +97,16 @@ class RichTextMobileTabletController extends GetxController { bool isTextStyleTypeSelected(RichTextStyleType richTextStyleType) { return listTextStyleApply.contains(richTextStyleType); } + + void applyNewFontStyle(SafeFont? newFont) { + final fontSelected = newFont ?? SafeFont.sansSerif; + selectedFontName.value = fontSelected; + htmlEditorApi?.setFont(selectedFontName.value); + } + + bool get isMenuFontOpen => menuFontStatus == DropdownMenuFontStatus.open; + + void closeDropdownMenuFont() { + popBack(); + } } diff --git a/pubspec.yaml b/pubspec.yaml index 3818f2ff4..6d8ca45b4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -124,7 +124,7 @@ dependencies: # enough_html_editor: Compose email for Mobile & Tablet enough_html_editor: git: - url: https://github.com/dab246/enough_html_editor.git + url: https://github.com/ManhNTX/enough_html_editor.git ref: improvements_for_use_tmail # html_editor_enhanced: Compose email for Web Browser