TF-733 Apply change text color to body composer on web

This commit is contained in:
dab246
2022-07-21 13:19:22 +07:00
committed by Dat H. Pham
parent 791656df9b
commit 50316bfa15
8 changed files with 260 additions and 13 deletions
@@ -158,4 +158,40 @@ Widget buildButtonWrapText(String name, {
color: Colors.white)),
),
);
}
Widget buildButtonWrapText(String name, {
TextStyle? textStyle,
Color? bgColor,
Color? borderColor,
double? radius,
double? height,
EdgeInsets? padding,
IconWebCallback? onTap
}) {
return Container(
height: height ?? 40,
padding: padding,
child: ElevatedButton(
onPressed: () => onTap?.call(),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) => bgColor ?? AppColor.colorTextButton),
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(radius ?? 8),
side: BorderSide(
width: borderColor != null ? 1 : 0,
color: borderColor ?? bgColor ?? AppColor.colorTextButton))),
padding: MaterialStateProperty.resolveWith<EdgeInsets>(
(Set<MaterialState> states) => const EdgeInsets.symmetric(horizontal: 16)),
elevation: MaterialStateProperty.resolveWith<double>(
(Set<MaterialState> states) => 0)),
child: Text(name,
textAlign: TextAlign.center,
style: textStyle ??
const TextStyle(
fontSize: 17,
fontWeight: FontWeight.w500,
color: Colors.white)),
),
);
}
@@ -65,7 +65,7 @@ class ComposerView extends GetWidget<ComposerController>
Expanded(child: Column(
children: [
_buildAttachmentsWidget(context),
_buildToolbarRichTextWidget(),
_buildToolbarRichTextWidget(context),
_buildInlineLoadingView(),
_buildEditorForm(context)
]
@@ -299,7 +299,7 @@ class ComposerView extends GetWidget<ComposerController>
child: Column(
children: [
_buildAttachmentsWidget(context),
_buildToolbarRichTextWidget(),
_buildToolbarRichTextWidget(context),
_buildInlineLoadingView(),
_buildEditorForm(context)
]
@@ -734,15 +734,25 @@ class ComposerView extends GetWidget<ComposerController>
}
}
Widget _buildToolbarRichTextWidget() {
Widget _buildToolbarRichTextWidget(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 20, top: 4, bottom: 8),
child: Row(
children: RichTextStyleType.values.map((textType) => Obx(() {
return buildIconStyleText(
path: textType.getIcon(imagePaths),
isSelected: controller.richTextWebController.isTextStyleTypeSelected(textType),
onTap: () => controller.richTextWebController.applyRichTextStyle(textType));
switch(textType) {
case RichTextStyleType.textColor:
return buildIconColorText(
iconData: textType.getIconData(),
colorSelected: controller.richTextWebController.selectedTextColor.value,
tooltip: textType.getTooltipButton(context),
onTap: () => controller.richTextWebController.applyRichTextStyle(context, textType));
default:
return buildIconStyleText(
path: textType.getIcon(imagePaths),
isSelected: controller.richTextWebController.isTextStyleTypeSelected(textType),
tooltip: textType.getTooltipButton(context),
onTap: () => controller.richTextWebController.applyRichTextStyle(context, textType));
}
})).toList()
),
);
@@ -0,0 +1,29 @@
import 'package:core/presentation/views/dialog/color_picker_dialog_builder.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
abstract class BaseRichTextController extends GetxController {
void openMenuSelectColor(
BuildContext context,
Color currentColor,
{Function(Color?)? onSelectColor}
) async {
await ColorPickerDialogBuilder(
context,
currentColor,
title: AppLocalizations.of(context).chooseAColor,
textActionSetColor: AppLocalizations.of(context).setColor,
textActionResetDefault: AppLocalizations.of(context).resetToDefault,
textActionCancel: AppLocalizations.of(context).cancel,
cancelActionCallback: () => popBack(),
setColorActionCallback: (selectedColor) {
onSelectColor?.call(selectedColor);
popBack();
}
).show();
}
}
@@ -4,18 +4,22 @@ import 'package:dartz/dartz.dart';
import 'package:html/parser.dart' show parse;
import 'package:core/utils/app_logger.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:html_editor_enhanced/html_editor.dart';
import 'package:model/email/attachment.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/image_source.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart';
import 'package:tmail_ui_user/features/composer/presentation/controller/base_rich_text_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart';
class RichTextWebController extends GetxController {
class RichTextWebController extends BaseRichTextController {
final editorController = HtmlEditorController(processNewLineAsBr: true);
final listTextStyleApply = RxList<RichTextStyleType>();
final selectedTextColor = Colors.black.obs;
void onEditorSettingsChange(EditorSettings settings) {
log('RichTextWebController::onEditorSettingsChange():');
@@ -37,9 +41,32 @@ class RichTextWebController extends GetxController {
}
}
void applyRichTextStyle(RichTextStyleType textStyleType) {
editorController.execCommand(textStyleType.commandAction);
_selectTextStyleType(textStyleType);
void applyRichTextStyle(BuildContext context, RichTextStyleType textStyleType) {
switch(textStyleType) {
case RichTextStyleType.textColor:
openMenuSelectColor(
context,
selectedTextColor.value,
onSelectColor: (selectedColor) {
final newColor = selectedColor ?? Colors.black;
final colorAsString = (newColor.value & 0xFFFFFF)
.toRadixString(16)
.padLeft(6, '0')
.toUpperCase();
log('RichTextWebController::applyRichTextStyle(): color: $newColor');
log('RichTextWebController::applyRichTextStyle(): colorAsString: $colorAsString');
selectedTextColor.value = newColor;
editorController.execCommand(
textStyleType.commandAction,
argument: colorAsString);
}
);
break;
default:
editorController.execCommand(textStyleType.commandAction);
_selectTextStyleType(textStyleType);
break;
}
}
void _selectTextStyleType(RichTextStyleType textStyleType) {
@@ -10,6 +10,7 @@ mixin RichTextButtonMixin {
required String path,
required bool? isSelected,
required VoidCallback onTap,
String? tooltip
}){
return buildIconWeb(
icon: SvgPicture.asset(
@@ -21,6 +22,23 @@ mixin RichTextButtonMixin {
iconPadding: const EdgeInsets.all(4),
colorFocus: Colors.white,
minSize: 26,
tooltip: tooltip,
onTap: onTap,
);
}
Widget buildIconColorText({
required IconData? iconData,
required Color? colorSelected,
required VoidCallback onTap,
String? tooltip
}){
return buildIconWeb(
icon: Icon(iconData, color: colorSelected ?? Colors.black, size: 20),
iconPadding: const EdgeInsets.all(4),
colorFocus: Colors.white,
minSize: 20,
tooltip: tooltip,
onTap: onTap,
);
}
@@ -1,11 +1,14 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:flutter/material.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
enum RichTextStyleType {
bold,
italic,
underline,
strikeThrough;
strikeThrough,
textColor;
String get commandAction {
switch (this) {
@@ -17,6 +20,8 @@ enum RichTextStyleType {
return 'underline';
case strikeThrough:
return 'strikeThrough';
case textColor:
return 'foreColor';
default:
return '';
}
@@ -36,4 +41,30 @@ enum RichTextStyleType {
return '';
}
}
IconData? getIconData() {
switch (this) {
case textColor:
return Icons.format_color_text;
default:
return null;
}
}
String getTooltipButton(BuildContext context) {
switch (this) {
case bold:
return AppLocalizations.of(context).formatBold;
case italic:
return AppLocalizations.of(context).formatItalic;
case underline:
return AppLocalizations.of(context).formatUnderline;
case strikeThrough:
return AppLocalizations.of(context).formatStrikethrough;
case textColor:
return AppLocalizations.of(context).formatTextColor;
default:
return '';
}
}
}
+49 -1
View File
@@ -1,5 +1,5 @@
{
"@@last_modified": "2022-07-18T16:31:40.598846",
"@@last_modified": "2022-07-21T13:16:06.832687",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -1615,5 +1615,53 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"chooseAColor": "Choose a color",
"@chooseAColor": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"resetToDefault": "Reset to default",
"@resetToDefault": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"setColor": "Set color",
"@setColor": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"formatBold": "Bold",
"@formatBold": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"formatItalic": "Italic",
"@formatItalic": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"formatUnderline": "Underline",
"@formatUnderline": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"formatStrikethrough": "Strikethrough",
"@formatStrikethrough": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"formatTextColor": "Text Color",
"@formatTextColor": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
@@ -1659,4 +1659,52 @@ class AppLocalizations {
'Please input either an image or an image URL, not both',
name: 'insertImageErrorDuplicate');
}
String get chooseAColor {
return Intl.message(
'Choose a color',
name: 'chooseAColor');
}
String get resetToDefault {
return Intl.message(
'Reset to default',
name: 'resetToDefault');
}
String get setColor {
return Intl.message(
'Set color',
name: 'setColor');
}
String get formatBold {
return Intl.message(
'Bold',
name: 'formatBold');
}
String get formatItalic {
return Intl.message(
'Italic',
name: 'formatItalic');
}
String get formatUnderline {
return Intl.message(
'Underline',
name: 'formatUnderline');
}
String get formatStrikethrough {
return Intl.message(
'Strikethrough',
name: 'formatStrikethrough');
}
String get formatTextColor {
return Intl.message(
'Text Color',
name: 'formatTextColor');
}
}