TF-735 Display button code view in composer web
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.48633 13.9904C3.48633 14.1164 3.51299 14.2388 3.56631 14.3575C3.61962 14.4763 3.6996 14.5842 3.80624 14.6811L8.51039 18.9199C8.70427 19.0993 8.91754 19.1853 9.15021 19.178C9.38287 19.1708 9.57918 19.0774 9.73913 18.8981C9.89909 18.7139 9.97059 18.5055 9.95362 18.2728C9.93666 18.0402 9.83365 17.8414 9.64462 17.6766L5.58029 13.9904L9.64462 10.3041C9.83365 10.1345 9.93666 9.93333 9.95362 9.70066C9.97059 9.468 9.89909 9.262 9.73913 9.08265C9.57918 8.90331 9.38287 8.81 9.15021 8.80273C8.91754 8.79546 8.70427 8.8815 8.51039 9.06084L3.80624 13.2997C3.6996 13.3966 3.61962 13.5045 3.56631 13.6232C3.51299 13.742 3.48633 13.8644 3.48633 13.9904ZM11.9785 20.963C12.2209 21.0308 12.4426 21.0054 12.6438 20.8866C12.8449 20.7679 12.9819 20.5873 13.0546 20.345L16.6318 8.0793C16.7045 7.85148 16.6875 7.63699 16.5809 7.43584C16.4742 7.23468 16.2997 7.1026 16.0574 7.03958C15.8199 6.97173 15.6017 6.99111 15.403 7.09775C15.2043 7.20439 15.0686 7.391 14.9959 7.65759L11.4332 19.8651C11.3605 20.1172 11.3702 20.3462 11.4623 20.5522C11.5544 20.7582 11.7265 20.8951 11.9785 20.963ZM24.5132 13.9904C24.5132 13.8644 24.4878 13.742 24.4369 13.6232C24.386 13.5045 24.3072 13.3966 24.2006 13.2997L19.4964 9.06084C19.3025 8.8815 19.0905 8.79546 18.8602 8.80273C18.63 8.81 18.4325 8.90331 18.2677 9.08265C18.1029 9.262 18.029 9.468 18.0459 9.70066C18.0629 9.93333 18.1659 10.1345 18.3549 10.3041L22.4265 13.9904L18.3549 17.6766C18.1659 17.8414 18.0629 18.0402 18.0459 18.2728C18.029 18.5055 18.1029 18.7139 18.2677 18.8981C18.4325 19.0774 18.63 19.1708 18.8602 19.178C19.0905 19.1853 19.3025 19.0993 19.4964 18.9199L24.2006 14.6811C24.3072 14.5842 24.386 14.4763 24.4369 14.3575C24.4878 14.2388 24.5132 14.1164 24.5132 13.9904Z" fill="#99A2AD"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -133,6 +133,7 @@ class ImagePaths {
|
||||
String get icStyleUnderline => _getImagePath('ic_style_underline.svg');
|
||||
String get icInsertImage => _getImagePath('ic_insert_image.svg');
|
||||
String get icStyleStrikeThrough => _getImagePath('ic_style_strikethrough.svg');
|
||||
String get icStyleCodeView => _getImagePath('ic_style_code_view.svg');
|
||||
|
||||
String _getImagePath(String imageName) {
|
||||
return AssetsPaths.images + imageName;
|
||||
|
||||
@@ -16,22 +16,26 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
final List<T> items;
|
||||
final T? itemSelected;
|
||||
final Function(T?)? onChanged;
|
||||
final Function(bool)? onMenuStateChange;
|
||||
final bool supportHint;
|
||||
final bool supportSelectionIcon;
|
||||
final double heightItem;
|
||||
final double sizeIconChecked;
|
||||
final double radiusButton;
|
||||
final double opacity;
|
||||
|
||||
const DropDownButtonWidget({
|
||||
Key? key,
|
||||
required this.items,
|
||||
required this.itemSelected,
|
||||
this.onChanged,
|
||||
this.onMenuStateChange,
|
||||
this.supportHint = false,
|
||||
this.supportSelectionIcon = false,
|
||||
this.heightItem = 44,
|
||||
this.sizeIconChecked = 20,
|
||||
this.radiusButton = 10,
|
||||
this.opacity = 1.0,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -46,9 +50,9 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
? Row(children: [
|
||||
Expanded(child: Text(
|
||||
_getTextItemDropdown(context, item: itemSelected),
|
||||
style: const TextStyle(fontSize: 16,
|
||||
style: TextStyle(fontSize: 16,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Colors.black),
|
||||
color: Colors.black.withOpacity(opacity)),
|
||||
maxLines: 1,
|
||||
overflow: CommonTextStyle.defaultTextOverFlow,
|
||||
)),
|
||||
@@ -95,9 +99,9 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
child: Row(children: [
|
||||
Expanded(child: Text(
|
||||
_getTextItemDropdown(context, item: itemSelected),
|
||||
style: const TextStyle(fontSize: 16,
|
||||
style: TextStyle(fontSize: 16,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Colors.black),
|
||||
color: Colors.black.withOpacity(opacity)),
|
||||
maxLines: 1,
|
||||
overflow: CommonTextStyle.defaultTextOverFlow,
|
||||
)),
|
||||
@@ -131,6 +135,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
dropdownElevation: 4,
|
||||
scrollbarRadius: const Radius.circular(40),
|
||||
scrollbarThickness: 6,
|
||||
onMenuStateChange: onMenuStateChange,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -355,10 +355,6 @@ class ComposerController extends BaseController {
|
||||
return '';
|
||||
}
|
||||
|
||||
void setFullScreenEditor() {
|
||||
richTextWebController.editorController.setFullScreen();
|
||||
}
|
||||
|
||||
String? _getHeaderEmailQuoted(BuildContext context, ComposerArguments arguments) {
|
||||
final presentationEmail = arguments.presentationEmail;
|
||||
if (presentationEmail != null) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_b
|
||||
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/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';
|
||||
@@ -508,16 +509,22 @@ class ComposerView extends GetWidget<ComposerController>
|
||||
tooltip: AppLocalizations.of(context).attach_file,
|
||||
onTap: () => controller.openFilePickerByType(context, FileType.any)),
|
||||
const SizedBox(width: 4),
|
||||
buildIconWeb(
|
||||
minSize: 40,
|
||||
iconPadding: EdgeInsets.zero,
|
||||
icon: SvgPicture.asset(imagePaths.icInsertImage,
|
||||
color: AppColor.colorTextButton,
|
||||
fit: BoxFit.fill),
|
||||
tooltip: AppLocalizations.of(context).insertImage,
|
||||
onTap: () => controller.insertImage(
|
||||
context,
|
||||
maxWithEditor: constraints.maxWidth - 120)),
|
||||
Obx(() {
|
||||
final opacity = controller.richTextWebController.codeViewEnabled ? 0.5 : 1.0;
|
||||
return AbsorbPointer(
|
||||
absorbing: controller.richTextWebController.codeViewEnabled,
|
||||
child: buildIconWeb(
|
||||
minSize: 40,
|
||||
iconPadding: EdgeInsets.zero,
|
||||
icon: SvgPicture.asset(imagePaths.icInsertImage,
|
||||
color: AppColor.colorTextButton.withOpacity(opacity),
|
||||
fit: BoxFit.fill),
|
||||
tooltip: AppLocalizations.of(context).insertImage,
|
||||
onTap: () => controller.insertImage(
|
||||
context,
|
||||
maxWithEditor: constraints.maxWidth - 120)),
|
||||
);
|
||||
}),
|
||||
])
|
||||
)
|
||||
);
|
||||
@@ -598,27 +605,35 @@ class ComposerView extends GetWidget<ComposerController>
|
||||
toolbarType: ToolbarType.hide,
|
||||
defaultToolbarButtons: []),
|
||||
otherOptions: const OtherOptions(height: 550),
|
||||
callbacks: Callbacks(onBeforeCommand: (String? currentHtml) {
|
||||
callbacks: Callbacks(onBeforeCommand: (currentHtml) {
|
||||
log('ComposerView::_buildHtmlEditor(): onBeforeCommand : $currentHtml');
|
||||
controller.setTextEditorWeb(currentHtml);
|
||||
}, onChangeContent: (String? changed) {
|
||||
}, onChangeContent: (changed) {
|
||||
log('ComposerView::_buildHtmlEditor(): onChangeContent : $changed');
|
||||
controller.setTextEditorWeb(changed);
|
||||
}, onInit: () {
|
||||
log('ComposerView::_buildHtmlEditor(): onInit');
|
||||
controller.setTextEditorWeb(initContent);
|
||||
controller.setFullScreenEditor();
|
||||
controller.richTextWebController.setFullScreenEditor();
|
||||
controller.richTextWebController.setEnableCodeView();
|
||||
}, onFocus: () {
|
||||
log('ComposerView::_buildHtmlEditor(): onFocus');
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
controller.richTextWebController.editorController.setFocus();
|
||||
});
|
||||
if (controller.richTextWebController.isMenuFontOpen) {
|
||||
controller.richTextWebController.closeDropdownMenuFont();
|
||||
}
|
||||
}, onBlur: () {
|
||||
controller.onEditorFocusChange(false);
|
||||
}, onMouseDown: () {
|
||||
controller.onEditorFocusChange(true);
|
||||
}, onChangeSelection: (settings) {
|
||||
controller.richTextWebController.onEditorSettingsChange(settings);
|
||||
}, onChangeCodeview: (contentChanged) {
|
||||
log('ComposerView::_buildHtmlEditor(): onChangeCodeView : $contentChanged');
|
||||
controller.setTextEditorWeb(contentChanged);
|
||||
}),
|
||||
)
|
||||
)
|
||||
@@ -744,40 +759,70 @@ class ComposerView extends GetWidget<ComposerController>
|
||||
alignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: RichTextStyleType.values.map((textType) => Obx(() {
|
||||
final opacity = controller.richTextWebController.codeViewEnabled ? 0.5 : 1.0;
|
||||
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));
|
||||
return AbsorbPointer(
|
||||
absorbing: controller.richTextWebController.codeViewEnabled,
|
||||
child: buildIconColorText(
|
||||
iconData: textType.getIconData(),
|
||||
colorSelected: controller.richTextWebController.selectedTextColor.value,
|
||||
tooltip: textType.getTooltipButton(context),
|
||||
opacity: opacity,
|
||||
onTap: () => controller.richTextWebController.applyRichTextStyle(context, textType)),
|
||||
);
|
||||
case RichTextStyleType.textBackgroundColor:
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
||||
child: buildIconColorBackgroundText(
|
||||
iconData: textType.getIconData(),
|
||||
colorSelected: controller.richTextWebController.selectedTextBackgroundColor.value,
|
||||
tooltip: textType.getTooltipButton(context),
|
||||
onTap: () => controller.richTextWebController.applyRichTextStyle(context, textType)),
|
||||
child: AbsorbPointer(
|
||||
absorbing: controller.richTextWebController.codeViewEnabled,
|
||||
child: buildIconColorBackgroundText(
|
||||
iconData: textType.getIconData(),
|
||||
colorSelected: controller.richTextWebController.selectedTextBackgroundColor.value,
|
||||
tooltip: textType.getTooltipButton(context),
|
||||
opacity: opacity,
|
||||
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 AbsorbPointer(
|
||||
absorbing: controller.richTextWebController.codeViewEnabled,
|
||||
child: 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),
|
||||
onMenuStateChange: (isOpen) {
|
||||
log('ComposerView::_buildToolbarRichTextWidget(): MenuFontStatus: $isOpen');
|
||||
final newStatus = isOpen
|
||||
? DropdownMenuFontStatus.open
|
||||
: DropdownMenuFontStatus.closed;
|
||||
controller.richTextWebController.menuFontStatus = newStatus;
|
||||
},
|
||||
heightItem: 35,
|
||||
sizeIconChecked: 16,
|
||||
radiusButton: 5,
|
||||
opacity: opacity,
|
||||
supportSelectionIcon: true)),
|
||||
);
|
||||
case RichTextStyleType.codeView:
|
||||
return buildIconStyleText(
|
||||
path: textType.getIcon(imagePaths),
|
||||
isSelected: controller.richTextWebController.isTextStyleTypeSelected(textType),
|
||||
tooltip: textType.getTooltipButton(context),
|
||||
onTap: () => controller.richTextWebController.applyRichTextStyle(context, textType));
|
||||
onTap: () => controller.richTextWebController.toggleCodeView());
|
||||
default:
|
||||
return AbsorbPointer(
|
||||
absorbing: controller.richTextWebController.codeViewEnabled,
|
||||
child: buildIconStyleText(
|
||||
path: textType.getIcon(imagePaths),
|
||||
isSelected: controller.richTextWebController.isTextStyleTypeSelected(textType),
|
||||
tooltip: textType.getTooltipButton(context),
|
||||
opacity: opacity,
|
||||
onTap: () => controller.richTextWebController.applyRichTextStyle(context, textType)),
|
||||
);
|
||||
}
|
||||
})).toList()
|
||||
),
|
||||
|
||||
@@ -10,14 +10,15 @@ mixin RichTextButtonMixin {
|
||||
required String path,
|
||||
required bool? isSelected,
|
||||
required VoidCallback onTap,
|
||||
String? tooltip
|
||||
String? tooltip,
|
||||
double opacity = 1.0,
|
||||
}){
|
||||
return buildIconWeb(
|
||||
icon: SvgPicture.asset(
|
||||
path,
|
||||
color: isSelected == true
|
||||
? Colors.black
|
||||
: AppColor.colorDefaultRichTextButton,
|
||||
? Colors.black.withOpacity(opacity)
|
||||
: AppColor.colorDefaultRichTextButton.withOpacity(opacity),
|
||||
fit: BoxFit.fill),
|
||||
iconPadding: const EdgeInsets.all(4),
|
||||
colorFocus: Colors.white,
|
||||
@@ -31,10 +32,13 @@ mixin RichTextButtonMixin {
|
||||
required IconData? iconData,
|
||||
required Color? colorSelected,
|
||||
required VoidCallback onTap,
|
||||
String? tooltip
|
||||
String? tooltip,
|
||||
double opacity = 1.0,
|
||||
}){
|
||||
return buildIconWeb(
|
||||
icon: Icon(iconData, color: colorSelected ?? Colors.black, size: 20),
|
||||
icon: Icon(iconData,
|
||||
color: (colorSelected ?? Colors.black).withOpacity(opacity),
|
||||
size: 20),
|
||||
iconPadding: const EdgeInsets.all(4),
|
||||
colorSelected: colorSelected == Colors.white
|
||||
? AppColor.colorFocusRichTextButton
|
||||
@@ -50,13 +54,16 @@ mixin RichTextButtonMixin {
|
||||
required IconData? iconData,
|
||||
required Color? colorSelected,
|
||||
required VoidCallback onTap,
|
||||
String? tooltip
|
||||
String? tooltip,
|
||||
double opacity = 1.0,
|
||||
}){
|
||||
final newColor = colorSelected == Colors.white
|
||||
? AppColor.colorDefaultRichTextButton
|
||||
: colorSelected;
|
||||
return buildIconWeb(
|
||||
icon: Icon(iconData, color: newColor ?? AppColor.colorDefaultRichTextButton, size: 20),
|
||||
icon: Icon(iconData,
|
||||
color: (newColor ?? AppColor.colorDefaultRichTextButton).withOpacity(opacity),
|
||||
size: 20),
|
||||
iconPadding: const EdgeInsets.all(4),
|
||||
colorSelected: newColor == Colors.white
|
||||
? AppColor.colorFocusRichTextButton
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"@@last_modified": "2022-07-21T14:49:43.482260",
|
||||
"@@last_modified": "2022-07-22T14:15:06.629292",
|
||||
"initializing_data": "Initializing data...",
|
||||
"@initializing_data": {
|
||||
"type": "text",
|
||||
@@ -1669,5 +1669,11 @@
|
||||
"type": "text",
|
||||
"placeholders_order": [],
|
||||
"placeholders": {}
|
||||
},
|
||||
"codeView": "Code view",
|
||||
"@codeView": {
|
||||
"type": "text",
|
||||
"placeholders_order": [],
|
||||
"placeholders": {}
|
||||
}
|
||||
}
|
||||
@@ -1713,4 +1713,10 @@ class AppLocalizations {
|
||||
'Text Background Color',
|
||||
name: 'formatTextBackgroundColor');
|
||||
}
|
||||
|
||||
String get codeView {
|
||||
return Intl.message(
|
||||
'Code view',
|
||||
name: 'codeView');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user