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
@@ -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: