diff --git a/assets/images/ic_style_code_view.svg b/assets/images/ic_style_code_view.svg
new file mode 100644
index 000000000..5afd5da90
--- /dev/null
+++ b/assets/images/ic_style_code_view.svg
@@ -0,0 +1,3 @@
+
diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart
index 2c652ade5..854b9e078 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -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;
diff --git a/lib/features/base/widget/drop_down_button_widget.dart b/lib/features/base/widget/drop_down_button_widget.dart
index a4b92c775..4e5b468f4 100644
--- a/lib/features/base/widget/drop_down_button_widget.dart
+++ b/lib/features/base/widget/drop_down_button_widget.dart
@@ -16,22 +16,26 @@ class DropDownButtonWidget extends StatelessWidget {
final List 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 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 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 extends StatelessWidget {
dropdownElevation: 4,
scrollbarRadius: const Radius.circular(40),
scrollbarThickness: 6,
+ onMenuStateChange: onMenuStateChange,
),
),
);
diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart
index adec96dc7..2461e156c 100644
--- a/lib/features/composer/presentation/composer_controller.dart
+++ b/lib/features/composer/presentation/composer_controller.dart
@@ -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) {
diff --git a/lib/features/composer/presentation/composer_view_web.dart b/lib/features/composer/presentation/composer_view_web.dart
index 487cdfcf3..4b02efe66 100644
--- a/lib/features/composer/presentation/composer_view_web.dart
+++ b/lib/features/composer/presentation/composer_view_web.dart
@@ -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
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
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
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(
- 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(
+ 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()
),
diff --git a/lib/features/composer/presentation/mixin/rich_text_button_mixin.dart b/lib/features/composer/presentation/mixin/rich_text_button_mixin.dart
index 8787ee03d..3a4574f9f 100644
--- a/lib/features/composer/presentation/mixin/rich_text_button_mixin.dart
+++ b/lib/features/composer/presentation/mixin/rich_text_button_mixin.dart
@@ -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
diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb
index 4479c2ec0..e47c7bd3c 100644
--- a/lib/l10n/intl_messages.arb
+++ b/lib/l10n/intl_messages.arb
@@ -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": {}
}
}
\ No newline at end of file
diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart
index b1882d2cb..60a93c9b4 100644
--- a/lib/main/localizations/app_localizations.dart
+++ b/lib/main/localizations/app_localizations.dart
@@ -1713,4 +1713,10 @@ class AppLocalizations {
'Text Background Color',
name: 'formatTextBackgroundColor');
}
+
+ String get codeView {
+ return Intl.message(
+ 'Code view',
+ name: 'codeView');
+ }
}
\ No newline at end of file