diff --git a/core/lib/presentation/constants/color_picker_key_values.dart b/core/lib/presentation/constants/color_picker_key_values.dart new file mode 100644 index 0000000000..545fcf006a --- /dev/null +++ b/core/lib/presentation/constants/color_picker_key_values.dart @@ -0,0 +1,10 @@ +import 'dart:ui'; + +class ColorPickerKeyValues { + static const String colorPickerCancelButton = 'tmail_color_picker_cancel_button'; + static const String colorPickerResetToDefaultButton = 'tmail_color_picker_reset_to_default_button'; + static const String colorPickerSetButton = 'tmail_color_picker_set_button'; + static const String colorPickerCopyButton = 'tmail_color_picker_copy_button'; + + static String colorPickerOption(Color color) => 'tmail_color_picker_option_$color'; +} \ No newline at end of file diff --git a/core/lib/presentation/views/button/icon_button_web.dart b/core/lib/presentation/views/button/icon_button_web.dart index 1269ab16e7..6ffc8a1c9e 100644 --- a/core/lib/presentation/views/button/icon_button_web.dart +++ b/core/lib/presentation/views/button/icon_button_web.dart @@ -121,34 +121,38 @@ Widget buildButtonWrapText(String name, { double? minWidth, EdgeInsetsGeometry? padding, FocusNode? focusNode, + String? semanticIdentifier, IconWebCallback? onTap }) { return Container( height: height ?? 40, padding: padding, constraints: BoxConstraints(minWidth: minWidth ?? 0), - child: ElevatedButton( - focusNode: focusNode, - onPressed: () => onTap?.call(), - style: ButtonStyle( - backgroundColor: WidgetStateProperty.resolveWith( - (Set states) => bgColor ?? AppColor.colorTextButton), - shape: WidgetStateProperty.all(RoundedRectangleBorder( - borderRadius: BorderRadius.circular(radius ?? 8), - side: BorderSide( - width: borderColor != null ? 1 : 0, - color: borderColor ?? bgColor ?? AppColor.colorTextButton))), - padding: WidgetStateProperty.resolveWith( - (Set states) => const EdgeInsets.symmetric(horizontal: 16)), - elevation: WidgetStateProperty.resolveWith( - (Set states) => 0)), - child: Text(name, - textAlign: TextAlign.center, - style: textStyle ?? - const TextStyle( - fontSize: 17, - fontWeight: FontWeight.w500, - color: Colors.white)), + child: Semantics( + identifier: semanticIdentifier, + child: ElevatedButton( + focusNode: focusNode, + onPressed: () => onTap?.call(), + style: ButtonStyle( + backgroundColor: WidgetStateProperty.resolveWith( + (Set states) => bgColor ?? AppColor.colorTextButton), + shape: WidgetStateProperty.all(RoundedRectangleBorder( + borderRadius: BorderRadius.circular(radius ?? 8), + side: BorderSide( + width: borderColor != null ? 1 : 0, + color: borderColor ?? bgColor ?? AppColor.colorTextButton))), + padding: WidgetStateProperty.resolveWith( + (Set states) => const EdgeInsets.symmetric(horizontal: 16)), + elevation: WidgetStateProperty.resolveWith( + (Set states) => 0)), + child: Text(name, + textAlign: TextAlign.center, + style: textStyle ?? + const TextStyle( + fontSize: 17, + fontWeight: FontWeight.w500, + color: Colors.white)), + ), ), ); } \ No newline at end of file diff --git a/core/lib/presentation/views/dialog/color_picker_dialog_builder.dart b/core/lib/presentation/views/dialog/color_picker_dialog_builder.dart index 4bd8b2e477..ae3e8b75c2 100644 --- a/core/lib/presentation/views/dialog/color_picker_dialog_builder.dart +++ b/core/lib/presentation/views/dialog/color_picker_dialog_builder.dart @@ -1,4 +1,5 @@ +import 'package:core/presentation/constants/color_picker_key_values.dart'; import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/views/button/icon_button_web.dart'; import 'package:flex_color_picker/flex_color_picker.dart'; @@ -82,28 +83,32 @@ class ColorPickerDialogBuilder { ), Padding( padding: const EdgeInsets.symmetric(vertical: 16), - child: ColorCodeField( - color: _currentColor.value, - colorCodeHasColor: true, - shouldUpdate: _shouldUpdate, - onColorChanged: (Color color) { - if (AppColor.listColorsPicker.any((element) => element.value == color.value)) { - _shouldUpdate = true; - _currentColor.value = color; - } else { - _shouldUpdate = false; - _currentColor.value = Colors.black; - _colorCode = color; - } - }, - onEditFocused: (bool editInFocus) { - _shouldUpdate = editInFocus ? true : false; - }, - copyPasteBehavior: const ColorPickerCopyPasteBehavior( - parseShortHexCode: true, - ), - toolIcons: const ColorPickerActionButtons( - dialogActionButtons: true, + child: Semantics( + excludeSemantics: true, + identifier: ColorPickerKeyValues.colorPickerCopyButton, + child: ColorCodeField( + color: _currentColor.value, + colorCodeHasColor: true, + shouldUpdate: _shouldUpdate, + onColorChanged: (Color color) { + if (AppColor.listColorsPicker.any((element) => element.value == color.value)) { + _shouldUpdate = true; + _currentColor.value = color; + } else { + _shouldUpdate = false; + _currentColor.value = Colors.black; + _colorCode = color; + } + }, + onEditFocused: (bool editInFocus) { + _shouldUpdate = editInFocus ? true : false; + }, + copyPasteBehavior: const ColorPickerCopyPasteBehavior( + parseShortHexCode: true, + ), + toolIcons: const ColorPickerActionButtons( + dialogActionButtons: true, + ), ), ), ), @@ -121,7 +126,8 @@ class ColorPickerDialogBuilder { fontSize: 16, fontWeight: FontWeight.normal), bgColor: AppColor.colorShadowComposer, - onTap: () => cancelActionCallback?.call()), + onTap: () => cancelActionCallback?.call(), + semanticIdentifier: ColorPickerKeyValues.colorPickerCancelButton), buildButtonWrapText( textActionResetDefault ?? '', radius: 5, @@ -132,7 +138,8 @@ class ColorPickerDialogBuilder { fontWeight: FontWeight.normal), bgColor: Colors.white, borderColor: Colors.black26, - onTap: () => resetToDefaultActionCallback?.call()), + onTap: () => resetToDefaultActionCallback?.call(), + semanticIdentifier: ColorPickerKeyValues.colorPickerResetToDefaultButton), buildButtonWrapText( textActionSetColor ?? '', radius: 5, @@ -147,7 +154,8 @@ class ColorPickerDialogBuilder { } else { setColorActionCallback?.call(_currentColor.value); } - }) + }, + semanticIdentifier: ColorPickerKeyValues.colorPickerSetButton), ], ), ) @@ -157,21 +165,25 @@ class ColorPickerDialogBuilder { Widget _itemColorWidget(BuildContext context, Color color) { return Material( color: Colors.transparent, - child: InkWell( - onTap: () { - _shouldUpdate = true; - _currentColor.value = color; - }, - child: Container( - decoration: BoxDecoration( - color: color, - border: Border.all( - color: _currentColor.value == color ? Colors.white : Colors.transparent, - width: 8, + child: Semantics( + excludeSemantics: true, + identifier: ColorPickerKeyValues.colorPickerOption(color), + child: InkWell( + onTap: () { + _shouldUpdate = true; + _currentColor.value = color; + }, + child: Container( + decoration: BoxDecoration( + color: color, + border: Border.all( + color: _currentColor.value == color ? Colors.white : Colors.transparent, + width: 8, + ), ), + width: 40, + height: 40, ), - width: 40, - height: 40, ), ), ); diff --git a/lib/features/base/key_values/composer_key_values.dart b/lib/features/base/key_values/composer_key_values.dart index bfdb88214f..6e2e02fc60 100644 --- a/lib/features/base/key_values/composer_key_values.dart +++ b/lib/features/base/key_values/composer_key_values.dart @@ -32,5 +32,11 @@ class ComposerKeyValues { static const String richtextUnderlineToggle = 'tmail_composer_richtext_underline_toggle'; static const String richtextStrikethroughToggle = 'tmail_composer_richtext_strikethrough_toggle'; static const String richtextAlignParagraphButton = 'tmail_composer_richtext_align_paragraph_button'; - static const String richtextListStyleButton = 'tmail_composer_richtext_list_style_button'; + static const String richtextListStyleButton = 'tmail_composer_richtext_list_style_button'; + // Added on 17/09/2024 + static const String richtextHeaderStyleOption = 'tmail_composer_richtext_header_style_option'; + static const String richtextFontSizeOption = 'tmail_composer_richtext_font_size_option'; + static const String richtextFontNameOption = 'tmail_composer_richtext_font_name_option'; + static const String richtextAlignParagraphOption = 'tmail_composer_richtext_align_paragraph_option'; + static const String richtextListStyleOption = 'tmail_composer_richtext_list_style_option'; } \ No newline at end of file diff --git a/lib/features/base/widget/drop_down_button_widget.dart b/lib/features/base/widget/drop_down_button_widget.dart index 0492af8499..b6c1a7b2f7 100644 --- a/lib/features/base/widget/drop_down_button_widget.dart +++ b/lib/features/base/widget/drop_down_button_widget.dart @@ -33,6 +33,7 @@ class DropDownButtonWidget extends StatelessWidget { final double? dropdownWidth; final double? dropdownMaxHeight; final String? hintText; + final String? semanticIdentifier; const DropDownButtonWidget({ Key? key, @@ -52,6 +53,7 @@ class DropDownButtonWidget extends StatelessWidget { this.colorButton = Colors.white, this.tooltip = '', this.hintText, + this.semanticIdentifier, }) : super(key: key); @override @@ -80,6 +82,7 @@ class DropDownButtonWidget extends StatelessWidget { value: item, child: Semantics( excludeSemantics: true, + identifier: semanticIdentifier, child: PointerInterceptor( child: Container( color: Colors.transparent, diff --git a/lib/features/composer/presentation/model/order_list_type.dart b/lib/features/composer/presentation/model/order_list_type.dart index 57e4b4fb75..0dab72c13a 100644 --- a/lib/features/composer/presentation/model/order_list_type.dart +++ b/lib/features/composer/presentation/model/order_list_type.dart @@ -2,6 +2,7 @@ import 'package:core/core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:tmail_ui_user/features/base/key_values/composer_key_values.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; enum OrderListType { @@ -49,12 +50,16 @@ enum OrderListType { ImagePaths imagePaths, Function(OrderListType type) onActionCallback ) { - return buildIconWeb( - icon: SvgPicture.asset(getIcon(imagePaths)), - iconPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 5), - minSize: 30, - iconSize: 30, - tooltip: getTooltipButton(context), - onTap: () => onActionCallback.call(this)); + return Semantics( + identifier: ComposerKeyValues.richtextListStyleOption, + container: true, + child: buildIconWeb( + icon: SvgPicture.asset(getIcon(imagePaths)), + iconPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 5), + minSize: 30, + iconSize: 30, + tooltip: getTooltipButton(context), + onTap: () => onActionCallback.call(this)), + ); } } \ No newline at end of file diff --git a/lib/features/composer/presentation/model/paragraph_type.dart b/lib/features/composer/presentation/model/paragraph_type.dart index c85238fbf0..0217feb9a7 100644 --- a/lib/features/composer/presentation/model/paragraph_type.dart +++ b/lib/features/composer/presentation/model/paragraph_type.dart @@ -2,6 +2,7 @@ import 'package:core/core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:tmail_ui_user/features/base/key_values/composer_key_values.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; enum ParagraphType { @@ -85,12 +86,16 @@ enum ParagraphType { ImagePaths imagePaths, Function(ParagraphType paragraph) onActionCallback ) { - return buildIconWeb( - icon: SvgPicture.asset(getIcon(imagePaths)), - iconPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 5), - minSize: 30, - iconSize: 30, - tooltip: getTooltipButton(context), - onTap: () => onActionCallback.call(this)); + return Semantics( + identifier: ComposerKeyValues.richtextAlignParagraphOption, + container: true, + child: buildIconWeb( + icon: SvgPicture.asset(getIcon(imagePaths)), + iconPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 5), + minSize: 30, + iconSize: 30, + tooltip: getTooltipButton(context), + onTap: () => onActionCallback.call(this)), + ); } } \ No newline at end of file diff --git a/lib/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart b/lib/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart index c989590776..29ec1d7e2c 100644 --- a/lib/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart +++ b/lib/features/composer/presentation/widgets/drop_down_menu_header_style_widget.dart @@ -4,6 +4,7 @@ import 'package:core/presentation/utils/style_utils.dart'; import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; +import 'package:tmail_ui_user/features/base/key_values/composer_key_values.dart'; import 'package:tmail_ui_user/features/composer/presentation/model/header_style_type.dart'; class DropDownMenuHeaderStyleWidget extends StatelessWidget { @@ -36,6 +37,7 @@ class DropDownMenuHeaderStyleWidget extends StatelessWidget { value: item, child: Semantics( excludeSemantics: true, + identifier: ComposerKeyValues.richtextHeaderStyleOption, child: PointerInterceptor( child: Container( color: Colors.transparent, diff --git a/lib/features/composer/presentation/widgets/web/dropdown_menu_font_size_widget.dart b/lib/features/composer/presentation/widgets/web/dropdown_menu_font_size_widget.dart index d3446bee66..8b5254c79f 100644 --- a/lib/features/composer/presentation/widgets/web/dropdown_menu_font_size_widget.dart +++ b/lib/features/composer/presentation/widgets/web/dropdown_menu_font_size_widget.dart @@ -1,6 +1,7 @@ import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; +import 'package:tmail_ui_user/features/base/key_values/composer_key_values.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/styles/web/dropdown_menu_font_size_widget_style.dart'; import 'package:tmail_ui_user/features/composer/presentation/widgets/web/dropdown_button_font_size_widget.dart'; @@ -25,9 +26,13 @@ class DropdownMenuFontSizeWidget extends StatelessWidget { items: RichTextWebController.fontSizeList.map((value) { return DropdownMenuItem( value: value, - child: ItemMenuFontSizeWidget( - value: value, - selectedValue: selectedFontSize + child: Semantics( + excludeSemantics: true, + identifier: ComposerKeyValues.richtextFontSizeOption, + child: ItemMenuFontSizeWidget( + value: value, + selectedValue: selectedFontSize + ), ) ); }).toList(), diff --git a/lib/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart b/lib/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart index 513252d711..8a9461ddd8 100644 --- a/lib/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart +++ b/lib/features/composer/presentation/widgets/web/toolbar_rich_text_builder.dart @@ -102,6 +102,7 @@ class ToolbarRichTextWebBuilder extends StatelessWidget with RichTextButtonMixin identifier: ComposerKeyValues.richtextFontNameButton, child: DropDownButtonWidget( items: FontNameType.values, + semanticIdentifier: ComposerKeyValues.richtextFontNameOption, itemSelected: richTextWebController.selectedFontName.value, onChanged: (newFont) => richTextWebController.applyNewFontStyle(newFont), onMenuStateChange: (isOpen) {