add text_color background_color text_font setting
This commit is contained in:
@@ -3,6 +3,7 @@ import 'package:core/presentation/extensions/color_extension.dart';
|
|||||||
import 'package:core/presentation/resources/image_paths.dart';
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
import 'package:core/presentation/utils/style_utils.dart';
|
import 'package:core/presentation/utils/style_utils.dart';
|
||||||
import 'package:dropdown_button2/dropdown_button2.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/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -156,6 +157,9 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
|||||||
if (item is FontNameType) {
|
if (item is FontNameType) {
|
||||||
return item.fontFamily;
|
return item.fontFamily;
|
||||||
}
|
}
|
||||||
|
if (item is SafeFont) {
|
||||||
|
return item.name;
|
||||||
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,8 +10,10 @@ import 'package:get/get.dart';
|
|||||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||||
import 'package:model/model.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/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/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/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/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/attachment_file_composer_builder.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart';
|
||||||
@@ -460,10 +462,7 @@ class ComposerView extends GetWidget<ComposerController> with AppLoaderMixin, Ri
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 60, right: 25),
|
padding: const EdgeInsets.only(left: 60, right: 25),
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
Padding(
|
_buildToolbarRichTextWidget(context),
|
||||||
padding: const EdgeInsets.only(left: 22, top: 15),
|
|
||||||
child: Obx(() => _buildRowIconStyleText()),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Obx(() {
|
Obx(() {
|
||||||
final uploadAttachments = controller.uploadController.listUploadAttachments;
|
final uploadAttachments = controller.uploadController.listUploadAttachments;
|
||||||
@@ -493,46 +492,55 @@ class ComposerView extends GetWidget<ComposerController> with AppLoaderMixin, Ri
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildRowIconStyleText() {
|
Widget _buildToolbarRichTextWidget(BuildContext context) {
|
||||||
return Row(
|
return Container(
|
||||||
children: [
|
padding: const EdgeInsets.only(left: 20, top: 15, bottom: 8),
|
||||||
buildIconStyleText(
|
alignment: Alignment.centerLeft,
|
||||||
path: RichTextStyleType.bold.getIcon(imagePaths),
|
child: Wrap(
|
||||||
isSelected: controller.richTextMobileTabletController.isTextStyleTypeSelected(RichTextStyleType.bold),
|
alignment: WrapAlignment.center,
|
||||||
onTap: () async {
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
await controller.htmlEditorApi?.formatBold().then((value) {
|
children: RichTextStyleType.values.map((textType) => Obx(() {
|
||||||
controller.richTextMobileTabletController.selectTextStyleType(RichTextStyleType.bold);
|
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<SafeFont>(
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
),
|
})).toList()
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+73
-2
@@ -1,10 +1,19 @@
|
|||||||
import 'package:enough_html_editor/enough_html_editor.dart';
|
import 'package:enough_html_editor/enough_html_editor.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.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/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;
|
HtmlEditorApi? htmlEditorApi;
|
||||||
final listTextStyleApply = RxList<RichTextStyleType>();
|
final listTextStyleApply = RxList<RichTextStyleType>();
|
||||||
|
final selectedTextColor = Colors.black.obs;
|
||||||
|
final selectedTextBackgroundColor = Colors.white.obs;
|
||||||
|
final selectedFontName = SafeFont.sansSerif.obs;
|
||||||
|
|
||||||
|
DropdownMenuFontStatus menuFontStatus = DropdownMenuFontStatus.closed;
|
||||||
|
|
||||||
void listenHtmlEditorApi() {
|
void listenHtmlEditorApi() {
|
||||||
htmlEditorApi?.onFormatSettingsChanged = (formatSettings) {
|
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)) {
|
if (listTextStyleApply.contains(richTextStyleType)) {
|
||||||
listTextStyleApply.remove(richTextStyleType);
|
listTextStyleApply.remove(richTextStyleType);
|
||||||
} else {
|
} else {
|
||||||
@@ -38,4 +97,16 @@ class RichTextMobileTabletController extends GetxController {
|
|||||||
bool isTextStyleTypeSelected(RichTextStyleType richTextStyleType) {
|
bool isTextStyleTypeSelected(RichTextStyleType richTextStyleType) {
|
||||||
return listTextStyleApply.contains(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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -124,7 +124,7 @@ dependencies:
|
|||||||
# enough_html_editor: Compose email for Mobile & Tablet
|
# enough_html_editor: Compose email for Mobile & Tablet
|
||||||
enough_html_editor:
|
enough_html_editor:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/dab246/enough_html_editor.git
|
url: https://github.com/ManhNTX/enough_html_editor.git
|
||||||
ref: improvements_for_use_tmail
|
ref: improvements_for_use_tmail
|
||||||
|
|
||||||
# html_editor_enhanced: Compose email for Web Browser
|
# html_editor_enhanced: Compose email for Web Browser
|
||||||
|
|||||||
Reference in New Issue
Block a user