TF-733 Apply change font to body composer on web

This commit is contained in:
dab246
2022-07-21 15:41:59 +07:00
committed by Dat H. Pham
parent a98c646f53
commit ea64fe82e0
10 changed files with 213 additions and 133 deletions
@@ -1,3 +0,0 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.9678 21C15.045 21 15.9805 20.8288 16.7743 20.4863C17.5682 20.1439 18.1846 19.6598 18.6236 19.034C19.0625 18.4083 19.282 17.6782 19.282 16.8439C19.282 15.8352 18.9629 15.0429 18.3247 14.467C17.6865 13.891 16.6732 13.4474 15.2847 13.1361L13.6876 12.7718C12.7786 12.5602 12.1201 12.3064 11.7123 12.0107C11.3045 11.7149 11.1006 11.3211 11.1006 10.8292C11.1006 10.4307 11.2235 10.0758 11.4695 9.76451C11.7154 9.45319 12.0532 9.21192 12.4828 9.04069C12.9124 8.86947 13.4043 8.78386 13.9585 8.78386C14.4566 8.78386 14.9049 8.8539 15.3034 8.994C15.7018 9.13409 16.0443 9.34267 16.3307 9.61975C16.6171 9.89682 16.8475 10.2377 17.0218 10.6424C17.2273 11.0036 17.5262 11.1841 17.9184 11.1841C18.2048 11.1841 18.4321 11.1032 18.6002 10.9413C18.7683 10.7794 18.8524 10.5646 18.8524 10.2969C18.8524 10.2221 18.8477 10.1459 18.8384 10.068C18.829 9.99022 18.8119 9.91083 18.787 9.82989C18.6376 9.26951 18.3387 8.77763 17.8904 8.35424C17.4421 7.93084 16.8802 7.59929 16.2046 7.35957C15.5291 7.11986 14.7803 7 13.9585 7C12.9809 7 12.1123 7.16967 11.3527 7.50901C10.5931 7.84834 9.99693 8.31999 9.5642 8.92395C9.13146 9.52791 8.9151 10.2221 8.9151 11.0067C8.9151 11.9593 9.22486 12.7298 9.84438 13.3182C10.4639 13.9066 11.415 14.344 12.6976 14.6304L14.4535 15.032C15.3936 15.2562 16.0692 15.5255 16.4801 15.8399C16.8911 16.1543 17.0965 16.573 17.0965 17.0961C17.0965 17.507 16.9642 17.8728 16.6996 18.1935C16.435 18.5141 16.0676 18.7663 15.5976 18.95C15.1275 19.1336 14.5842 19.2255 13.9678 19.2255C13.4261 19.2255 12.9311 19.1477 12.4828 18.992C12.0345 18.8363 11.6485 18.6106 11.3247 18.3149C11.0009 18.0191 10.7519 17.6689 10.5775 17.2642C10.4655 17.0587 10.3425 16.9093 10.2086 16.8159C10.0748 16.7225 9.90198 16.6758 9.69028 16.6758C9.39764 16.6758 9.16571 16.7598 8.99448 16.928C8.82326 17.0961 8.73764 17.3202 8.73764 17.6004C8.73764 17.7934 8.76566 17.9864 8.8217 18.1795C8.99604 18.7585 9.32137 19.2582 9.79768 19.6785C10.274 20.0987 10.8686 20.4241 11.5815 20.6544C12.2945 20.8848 13.0899 21 13.9678 21ZM6.56153 14.4343H21.4394C21.5827 14.4343 21.7041 14.3829 21.8037 14.2802C21.9033 14.1775 21.9531 14.0576 21.9531 13.9206C21.9531 13.7836 21.9033 13.6638 21.8037 13.561C21.7041 13.4583 21.5827 13.4069 21.4394 13.4069H6.56153C6.41832 13.4069 6.29691 13.4583 6.19728 13.561C6.09766 13.6638 6.04785 13.7836 6.04785 13.9206C6.04785 14.0576 6.09766 14.1775 6.19728 14.2802C6.29691 14.3829 6.41832 14.4343 6.56153 14.4343Z" fill="#99A2AD"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -132,7 +132,7 @@ class ImagePaths {
String get icStyleItalic => _getImagePath('ic_style_italic.svg');
String get icStyleUnderline => _getImagePath('ic_style_underline.svg');
String get icInsertImage => _getImagePath('ic_insert_image.svg');
String get icStyleStrikeThrough => _getImagePath('ic_style_strikethroughs.svg');
String get icStyleStrikeThrough => _getImagePath('ic_style_strikethrough.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
@@ -126,39 +126,6 @@ Widget buildTextButton(String text, {
);
}
Widget buildButtonWrapText(String name, {
TextStyle? textStyle,
Color? bgColor,
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: 0, color: 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)),
),
);
}
Widget buildButtonWrapText(String name, {
TextStyle? textStyle,
Color? bgColor,
@@ -7,6 +7,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/font_name_type.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/language_and_region/extensions/locale_extension.dart';
class DropDownButtonWidget<T> extends StatelessWidget {
@@ -16,6 +18,9 @@ class DropDownButtonWidget<T> extends StatelessWidget {
final Function(T?)? onChanged;
final bool supportHint;
final bool supportSelectionIcon;
final double heightItem;
final double sizeIconChecked;
final double radiusButton;
const DropDownButtonWidget({
Key? key,
@@ -23,7 +28,10 @@ class DropDownButtonWidget<T> extends StatelessWidget {
required this.itemSelected,
this.onChanged,
this.supportHint = false,
this.supportSelectionIcon = false
this.supportSelectionIcon = false,
this.heightItem = 44,
this.sizeIconChecked = 20,
this.radiusButton = 10,
}) : super(key: key);
@override
@@ -31,92 +39,99 @@ class DropDownButtonWidget<T> extends StatelessWidget {
final _imagePaths = Get.find<ImagePaths>();
return DropdownButtonHideUnderline(
child: DropdownButton2<T>(
isExpanded: true,
hint: supportHint
? Row(children: [
Expanded(child: Text(
_getTextItemDropdown(context, item: itemSelected),
style: const TextStyle(fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
)),
])
: null,
items: items
.map((item) => DropdownMenuItem<T>(
value: item,
child: Row(children: [
Expanded(child: Text(_getTextItemDropdown(context, item: item),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
)),
if (supportSelectionIcon && item == itemSelected)
SvgPicture.asset(_imagePaths.icChecked,
width: 20,
height: 20,
fit: BoxFit.fill)
]),
))
.toList(),
value: itemSelected,
customButton: supportSelectionIcon
? Container(
height: 44,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: AppColor.colorInputBorderCreateMailbox,
width: 0.5,
child: PointerInterceptor(
child: DropdownButton2<T>(
isExpanded: true,
hint: supportHint
? Row(children: [
Expanded(child: Text(
_getTextItemDropdown(context, item: itemSelected),
style: const TextStyle(fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
)),
])
: null,
items: items
.map((item) => DropdownMenuItem<T>(
value: item,
child: PointerInterceptor(
child: SizedBox(
height: heightItem,
child: Row(children: [
Expanded(child: Text(_getTextItemDropdown(context, item: item),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
)),
if (supportSelectionIcon && item == itemSelected)
SvgPicture.asset(_imagePaths.icChecked,
width: sizeIconChecked,
height: sizeIconChecked,
fit: BoxFit.fill)
]),
),
),
))
.toList(),
value: itemSelected,
customButton: supportSelectionIcon
? Container(
height: heightItem,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(radiusButton),
border: Border.all(
color: AppColor.colorInputBorderCreateMailbox,
width: 0.5,
),
color: AppColor.colorInputBackgroundCreateMailbox,
),
color: AppColor.colorInputBackgroundCreateMailbox,
),
padding: const EdgeInsets.only(left: 12, right: 10),
child: Row(children: [
Expanded(child: Text(
_getTextItemDropdown(context, item: itemSelected),
style: const TextStyle(fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
)),
SvgPicture.asset(_imagePaths.icDropDown)
]),
)
: null,
onChanged: onChanged,
icon: SvgPicture.asset(_imagePaths.icDropDown),
buttonPadding: const EdgeInsets.symmetric(horizontal: 12),
buttonDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: AppColor.colorInputBorderCreateMailbox,
width: 0.5,
padding: const EdgeInsets.only(left: 12, right: 10),
child: Row(children: [
Expanded(child: Text(
_getTextItemDropdown(context, item: itemSelected),
style: const TextStyle(fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black),
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
)),
SvgPicture.asset(_imagePaths.icDropDown)
]),
)
: null,
onChanged: onChanged,
icon: SvgPicture.asset(_imagePaths.icDropDown),
buttonPadding: const EdgeInsets.symmetric(horizontal: 12),
buttonDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(radiusButton),
border: Border.all(
color: AppColor.colorInputBorderCreateMailbox,
width: 0.5,
),
color: AppColor.colorInputBackgroundCreateMailbox,
),
color: AppColor.colorInputBackgroundCreateMailbox,
itemHeight: heightItem,
buttonHeight: heightItem,
selectedItemHighlightColor: supportSelectionIcon
? Colors.white
: Colors.black12,
itemPadding: const EdgeInsets.symmetric(horizontal: 12),
dropdownMaxHeight: 200,
dropdownDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(radiusButton),
color: Colors.white,
),
offset: const Offset(0.0, -8.0),
dropdownElevation: 4,
scrollbarRadius: const Radius.circular(40),
scrollbarThickness: 6,
),
itemHeight: 44,
buttonHeight: 44,
selectedItemHighlightColor: supportSelectionIcon
? Colors.white
: Colors.black12,
itemPadding: const EdgeInsets.symmetric(horizontal: 12),
dropdownMaxHeight: 200,
dropdownDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
),
offset: const Offset(0.0, -8.0),
dropdownElevation: 4,
scrollbarRadius: const Radius.circular(40),
scrollbarThickness: 6,
),
);
}
@@ -128,6 +143,9 @@ class DropDownButtonWidget<T> extends StatelessWidget {
if (item is Locale) {
return item.getLanguageName(context);
}
if (item is FontNameType) {
return item.fontFamily;
}
return '';
}
}
@@ -11,8 +11,10 @@ import 'package:model/model.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_base64_state.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/font_name_type.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_file_composer_builder.dart';
@@ -736,9 +738,11 @@ class ComposerView extends GetWidget<ComposerController>
Widget _buildToolbarRichTextWidget(BuildContext context) {
return Container(
padding: const EdgeInsets.only(left: 20, top: 4, bottom: 8),
padding: const EdgeInsets.only(left: 20, top: 8, bottom: 8),
alignment: Alignment.centerLeft,
child: Wrap(
alignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
children: RichTextStyleType.values.map((textType) => Obx(() {
switch(textType) {
case RichTextStyleType.textColor:
@@ -750,12 +754,24 @@ class ComposerView extends GetWidget<ComposerController>
case RichTextStyleType.textBackgroundColor:
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 2),
child: buildIconColorText(
child: buildIconColorBackgroundText(
iconData: textType.getIconData(),
colorSelected: controller.richTextWebController.selectedTextBackgroundColor.value,
tooltip: textType.getTooltipButton(context),
onTap: () => controller.richTextWebController.applyRichTextStyle(context, textType)),
);
case RichTextStyleType.fontName:
return Container(
width: 200,
padding: const EdgeInsets.only(right: 2),
child: DropDownButtonWidget<FontNameType>(
items: FontNameType.values,
itemSelected: controller.richTextWebController.selectedFontName.value,
onChanged: (newFont) => controller.richTextWebController.applyNewFontStyle(newFont),
heightItem: 35,
sizeIconChecked: 16,
radiusButton: 5,
supportSelectionIcon: true));
default:
return buildIconStyleText(
path: textType.getIcon(imagePaths),
@@ -5,13 +5,13 @@ 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/font_name_type.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart';
class RichTextWebController extends BaseRichTextController {
@@ -20,7 +20,8 @@ class RichTextWebController extends BaseRichTextController {
final listTextStyleApply = RxList<RichTextStyleType>();
final selectedTextColor = Colors.black.obs;
final selectedTextBackgroundColor = Colors.transparent.obs;
final selectedTextBackgroundColor = Colors.white.obs;
final selectedFontName = FontNameType.sansSerif.obs;
void onEditorSettingsChange(EditorSettings settings) {
log('RichTextWebController::onEditorSettingsChange():');
@@ -77,17 +78,18 @@ class RichTextWebController extends BaseRichTextController {
context,
selectedTextBackgroundColor.value,
onResetToDefault: () {
final colorAsString = (Colors.transparent.value & 0xFFFFFF)
final colorAsString = (Colors.white.value & 0xFFFFFF)
.toRadixString(16)
.padLeft(6, '0')
.toUpperCase();
selectedTextBackgroundColor.value = Colors.transparent;
log('RichTextWebController::applyRichTextStyle():onResetToDefault: colorAsString: $colorAsString');
selectedTextBackgroundColor.value = Colors.white;
editorController.execCommand(
textStyleType.commandAction,
argument: colorAsString);
},
onSelectColor: (selectedColor) {
final newColor = selectedColor ?? Colors.transparent;
final newColor = selectedColor ?? Colors.white;
final colorAsString = (newColor.value & 0xFFFFFF)
.toRadixString(16)
.padLeft(6, '0')
@@ -155,4 +157,12 @@ class RichTextWebController extends BaseRichTextController {
log('RichTextWebController::refactorContentHasInlineImage(): listInlineAttachment: $listInlineAttachment');
return Tuple2(newContent, listInlineAttachment);
}
void applyNewFontStyle(FontNameType? newFont) {
final fontSelected = newFont ?? FontNameType.sansSerif;
selectedFontName.value = fontSelected;
editorController.execCommand(
RichTextStyleType.fontName.commandAction,
argument: fontSelected.fontFamily);
}
}
@@ -33,13 +33,10 @@ mixin RichTextButtonMixin {
required VoidCallback onTap,
String? tooltip
}){
final newColor = colorSelected == Colors.transparent
? AppColor.colorDefaultRichTextButton
: colorSelected;
return buildIconWeb(
icon: Icon(iconData, color: newColor ?? Colors.black, size: 20),
icon: Icon(iconData, color: colorSelected ?? Colors.black, size: 20),
iconPadding: const EdgeInsets.all(4),
colorSelected: newColor == Colors.white
colorSelected: colorSelected == Colors.white
? AppColor.colorFocusRichTextButton
: Colors.transparent,
colorFocus: Colors.white,
@@ -48,4 +45,26 @@ mixin RichTextButtonMixin {
onTap: onTap,
);
}
Widget buildIconColorBackgroundText({
required IconData? iconData,
required Color? colorSelected,
required VoidCallback onTap,
String? tooltip
}){
final newColor = colorSelected == Colors.white
? AppColor.colorDefaultRichTextButton
: colorSelected;
return buildIconWeb(
icon: Icon(iconData, color: newColor ?? AppColor.colorDefaultRichTextButton, size: 20),
iconPadding: const EdgeInsets.all(4),
colorSelected: newColor == Colors.white
? AppColor.colorFocusRichTextButton
: Colors.transparent,
colorFocus: Colors.white,
minSize: 20,
tooltip: tooltip,
onTap: onTap,
);
}
}
@@ -0,0 +1,50 @@
enum FontNameType {
arial,
arialBlack,
brushScriptMT,
comicSansMS,
courierNew,
helveticaNeue,
helvetica,
impact,
lucidaGrande,
tahoma,
timesNewRoman,
trebuchetMS,
sansSerif,
verdana;
String get fontFamily {
switch(this) {
case FontNameType.arial:
return 'Arial';
case FontNameType.arialBlack:
return 'Arial Black';
case FontNameType.brushScriptMT:
return 'Brush Script MT';
case FontNameType.comicSansMS:
return 'Comic Sans MS';
case FontNameType.courierNew:
return 'Courier New';
case FontNameType.helveticaNeue:
return 'Helvetica Neue';
case FontNameType.helvetica:
return 'Helvetica';
case FontNameType.impact:
return 'Impact';
case FontNameType.lucidaGrande:
return 'Lucida Grande';
case FontNameType.tahoma:
return 'Tahoma';
case FontNameType.timesNewRoman:
return 'Times New Roman';
case FontNameType.trebuchetMS:
return 'Trebuchet MS';
case FontNameType.sansSerif:
return 'Sans Serif';
case FontNameType.verdana:
return 'Verdana';
}
}
}
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
enum RichTextStyleType {
fontName,
bold,
italic,
underline,
@@ -13,6 +14,8 @@ enum RichTextStyleType {
String get commandAction {
switch (this) {
case fontName:
return 'fontName';
case bold:
return 'bold';
case italic: