Skip to content

Commit

Permalink
Add sample Semantics identifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
tddang-linagora committed Aug 29, 2024
1 parent 30525ff commit 9d2bdb9
Show file tree
Hide file tree
Showing 11 changed files with 253 additions and 178 deletions.
10 changes: 10 additions & 0 deletions core/lib/presentation/constants/search_key_values.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class SearchKeyValues {
static const String searchInputField = 'tmail_search_input_field';
static const String searchUserResult = 'tmail_search_user_result';
static const String searchEmailResult = 'tmail_search_email_result';
}

// When search input field is focused
// And search input field is not empty
// Then user result should be shown with maximum 2 results
// And email result should be shown with maximum 5 results
102 changes: 56 additions & 46 deletions core/lib/presentation/views/quick_search/quick_search_input_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:async';
import 'dart:io';
import 'dart:math';

import 'package:core/presentation/constants/search_key_values.dart';
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/direction_utils.dart';
Expand Down Expand Up @@ -850,47 +851,50 @@ class _TypeAheadFieldQuickSearchState<T, P, R> extends State<TypeAheadFieldQuick
if (widget.textFieldConfiguration.leftButton != null)
widget.textFieldConfiguration.leftButton!,
Expanded(
child: TextField(
focusNode: _effectiveFocusNode,
controller: _effectiveController,
decoration: widget.textFieldConfiguration.decoration,
style: widget.textFieldConfiguration.style,
textAlign: widget.textFieldConfiguration.textAlign,
enabled: widget.textFieldConfiguration.enabled,
keyboardType: widget.textFieldConfiguration.keyboardType,
autofocus: widget.textFieldConfiguration.autofocus,
inputFormatters: widget.textFieldConfiguration.inputFormatters,
autocorrect: widget.textFieldConfiguration.autocorrect,
maxLines: widget.textFieldConfiguration.maxLines,
textAlignVertical: widget.textFieldConfiguration.textAlignVertical,
minLines: widget.textFieldConfiguration.minLines,
maxLength: widget.textFieldConfiguration.maxLength,
maxLengthEnforcement: widget.textFieldConfiguration.maxLengthEnforcement,
obscureText: widget.textFieldConfiguration.obscureText,
onChanged: (input) {
widget.textFieldConfiguration.onChanged?.call(input);
if (input.isNotEmpty) {
final directionByText = DirectionUtils.getDirectionByEndsText(input);
if (directionByText != _textDirection) {
setState(() {
_textDirection = directionByText;
});
child: Semantics(
identifier: SearchKeyValues.searchInputField,
child: TextField(
focusNode: _effectiveFocusNode,
controller: _effectiveController,
decoration: widget.textFieldConfiguration.decoration,
style: widget.textFieldConfiguration.style,
textAlign: widget.textFieldConfiguration.textAlign,
enabled: widget.textFieldConfiguration.enabled,
keyboardType: widget.textFieldConfiguration.keyboardType,
autofocus: widget.textFieldConfiguration.autofocus,
inputFormatters: widget.textFieldConfiguration.inputFormatters,
autocorrect: widget.textFieldConfiguration.autocorrect,
maxLines: widget.textFieldConfiguration.maxLines,
textAlignVertical: widget.textFieldConfiguration.textAlignVertical,
minLines: widget.textFieldConfiguration.minLines,
maxLength: widget.textFieldConfiguration.maxLength,
maxLengthEnforcement: widget.textFieldConfiguration.maxLengthEnforcement,
obscureText: widget.textFieldConfiguration.obscureText,
onChanged: (input) {
widget.textFieldConfiguration.onChanged?.call(input);
if (input.isNotEmpty) {
final directionByText = DirectionUtils.getDirectionByEndsText(input);
if (directionByText != _textDirection) {
setState(() {
_textDirection = directionByText;
});
}
}
}
},
onSubmitted: widget.textFieldConfiguration.onSubmitted,
onEditingComplete: widget.textFieldConfiguration.onEditingComplete,
onTap: widget.textFieldConfiguration.onTap,
scrollPadding: widget.textFieldConfiguration.scrollPadding,
textInputAction: widget.textFieldConfiguration.textInputAction,
textCapitalization: widget.textFieldConfiguration.textCapitalization,
keyboardAppearance: widget.textFieldConfiguration.keyboardAppearance,
cursorWidth: widget.textFieldConfiguration.cursorWidth,
cursorRadius: widget.textFieldConfiguration.cursorRadius,
cursorColor: widget.textFieldConfiguration.cursorColor,
textDirection: _textDirection,
enableInteractiveSelection: widget.textFieldConfiguration.enableInteractiveSelection,
readOnly: widget.hideKeyboard,
},
onSubmitted: widget.textFieldConfiguration.onSubmitted,
onEditingComplete: widget.textFieldConfiguration.onEditingComplete,
onTap: widget.textFieldConfiguration.onTap,
scrollPadding: widget.textFieldConfiguration.scrollPadding,
textInputAction: widget.textFieldConfiguration.textInputAction,
textCapitalization: widget.textFieldConfiguration.textCapitalization,
keyboardAppearance: widget.textFieldConfiguration.keyboardAppearance,
cursorWidth: widget.textFieldConfiguration.cursorWidth,
cursorRadius: widget.textFieldConfiguration.cursorRadius,
cursorColor: widget.textFieldConfiguration.cursorColor,
textDirection: _textDirection,
enableInteractiveSelection: widget.textFieldConfiguration.enableInteractiveSelection,
readOnly: widget.hideKeyboard,
),
),
),
if (widget.textFieldConfiguration.clearTextButton != null
Expand Down Expand Up @@ -1202,9 +1206,12 @@ class _SuggestionsListState<T, P, R> extends State<_SuggestionsList<T, P, R>>
Widget createSuggestionsWidget() {
final listItemSuggestionWidget = _suggestions?.map((T suggestion) {
if (widget.itemBuilder != null) {
return InkWell(
child: widget.itemBuilder!(context, suggestion),
onTap: () => widget.onSuggestionSelected?.call(suggestion),
return Semantics(
identifier: SearchKeyValues.searchEmailResult,
child: InkWell(
child: widget.itemBuilder!(context, suggestion),
onTap: () => widget.onSuggestionSelected?.call(suggestion),
),
);
} else {
return const SizedBox.shrink();
Expand Down Expand Up @@ -1251,9 +1258,12 @@ class _SuggestionsListState<T, P, R> extends State<_SuggestionsList<T, P, R>>
if (widget.contactSuggestionBuilder != null) {
return Material(
type: MaterialType.transparency,
child: InkWell(
child: widget.contactSuggestionBuilder!(context, contact),
onTap: () => widget.onContactSuggestionSelected?.call(contact),
child: Semantics(
identifier: SearchKeyValues.searchUserResult,
child: InkWell(
child: widget.contactSuggestionBuilder!(context, contact),
onTap: () => widget.onContactSuggestionSelected?.call(contact),
),
),
);
} else {
Expand Down
6 changes: 6 additions & 0 deletions lib/features/base/key_values/login_basic_auth_key_values.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class LoginBasicAuthKeyValues {
static const String loginView = 'tmail_login_view';
static const String loginEmailField = 'tmail_login_email_field';
static const String loginPasswordField = 'tmail_login_password_field';
static const String loginSubmitButton = 'tmail_login_submit_button';
}
183 changes: 101 additions & 82 deletions lib/features/composer/presentation/view/web/web_editor_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:dartz/dartz.dart';
import 'package:flutter/material.dart';
import 'package:html_editor_enhanced/html_editor.dart';
import 'package:model/email/email_action_type.dart';
import 'package:tmail_ui_user/features/base/key_values/composer_key_values.dart';
import 'package:tmail_ui_user/features/composer/domain/state/restore_email_inline_images_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/view/editor_view_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/web/web_editor_widget.dart';
Expand Down Expand Up @@ -62,32 +63,9 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
case EmailActionType.compose:
case EmailActionType.composeFromEmailAddress:
case EmailActionType.composeFromFileShared:
return WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? HtmlExtension.editorStartTags,
direction: AppUtils.getCurrentDirection(context),
onInitial: onInitial,
onChangeContent: onChangeContent,
onFocus: onFocus,
onUnFocus: onUnFocus,
onMouseDown: onMouseDown,
onEditorSettings: onEditorSettings,
onEditorTextSizeChanged: onEditorTextSizeChanged,
width: width,
height: height,
onDragEnter: onDragEnter,
);
case EmailActionType.editDraft:
case EmailActionType.editSendingEmail:
case EmailActionType.composeFromContentShared:
case EmailActionType.reopenComposerBrowser:
case EmailActionType.composeFromUnsubscribeMailtoLink:
case EmailActionType.composeFromMailtoUri:
if (contentViewState == null) {
return const SizedBox.shrink();
}
return contentViewState!.fold(
(failure) => WebEditorWidget(
return Semantics(
identifier: ComposerKeyValues.composerContentField,
child: WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? HtmlExtension.editorStartTags,
direction: AppUtils.getCurrentDirection(context),
Expand All @@ -102,6 +80,35 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
height: height,
onDragEnter: onDragEnter,
),
);
case EmailActionType.editDraft:
case EmailActionType.editSendingEmail:
case EmailActionType.composeFromContentShared:
case EmailActionType.reopenComposerBrowser:
case EmailActionType.composeFromUnsubscribeMailtoLink:
case EmailActionType.composeFromMailtoUri:
if (contentViewState == null) {
return const SizedBox.shrink();
}
return contentViewState!.fold(
(failure) => Semantics(
identifier: ComposerKeyValues.composerContentField,
child: WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? HtmlExtension.editorStartTags,
direction: AppUtils.getCurrentDirection(context),
onInitial: onInitial,
onChangeContent: onChangeContent,
onFocus: onFocus,
onUnFocus: onUnFocus,
onMouseDown: onMouseDown,
onEditorSettings: onEditorSettings,
onEditorTextSizeChanged: onEditorTextSizeChanged,
width: width,
height: height,
onDragEnter: onDragEnter,
),
),
(success) {
if (success is GetEmailContentLoading || success is RestoringEmailInlineImages) {
return const CupertinoLoadingWidget(padding: EdgeInsets.all(16.0));
Expand All @@ -112,20 +119,23 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
if (newContent.isEmpty) {
newContent = HtmlExtension.editorStartTags;
}
return WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? newContent,
direction: AppUtils.getCurrentDirection(context),
onInitial: onInitial,
onChangeContent: onChangeContent,
onFocus: onFocus,
onUnFocus: onUnFocus,
onMouseDown: onMouseDown,
onEditorSettings: onEditorSettings,
onEditorTextSizeChanged: onEditorTextSizeChanged,
width: width,
height: height,
onDragEnter: onDragEnter,
return Semantics(
identifier: ComposerKeyValues.composerContentField,
child: WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? newContent,
direction: AppUtils.getCurrentDirection(context),
onInitial: onInitial,
onChangeContent: onChangeContent,
onFocus: onFocus,
onUnFocus: onUnFocus,
onMouseDown: onMouseDown,
onEditorSettings: onEditorSettings,
onEditorTextSizeChanged: onEditorTextSizeChanged,
width: width,
height: height,
onDragEnter: onDragEnter,
),
);
}
}
Expand All @@ -144,20 +154,23 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
emailActionType: arguments!.emailActionType,
presentationEmail: arguments!.presentationEmail!
);
return WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? emailContentQuoted,
direction: AppUtils.getCurrentDirection(context),
onInitial: onInitial,
onChangeContent: onChangeContent,
onFocus: onFocus,
onUnFocus: onUnFocus,
onMouseDown: onMouseDown,
onEditorSettings: onEditorSettings,
onEditorTextSizeChanged: onEditorTextSizeChanged,
width: width,
height: height,
onDragEnter: onDragEnter,
return Semantics(
identifier: ComposerKeyValues.composerContentField,
child: WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? emailContentQuoted,
direction: AppUtils.getCurrentDirection(context),
onInitial: onInitial,
onChangeContent: onChangeContent,
onFocus: onFocus,
onUnFocus: onUnFocus,
onMouseDown: onMouseDown,
onEditorSettings: onEditorSettings,
onEditorTextSizeChanged: onEditorTextSizeChanged,
width: width,
height: height,
onDragEnter: onDragEnter,
),
);
},
(success) {
Expand All @@ -172,39 +185,45 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
emailActionType: arguments!.emailActionType,
presentationEmail: arguments!.presentationEmail!
);
return WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? emailContentQuoted,
direction: AppUtils.getCurrentDirection(context),
onInitial: onInitial,
onChangeContent: onChangeContent,
onFocus: onFocus,
onUnFocus: onUnFocus,
onMouseDown: onMouseDown,
onEditorSettings: onEditorSettings,
onEditorTextSizeChanged: onEditorTextSizeChanged,
width: width,
height: height,
onDragEnter: onDragEnter,
return Semantics(
identifier: ComposerKeyValues.composerContentField,
child: WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? emailContentQuoted,
direction: AppUtils.getCurrentDirection(context),
onInitial: onInitial,
onChangeContent: onChangeContent,
onFocus: onFocus,
onUnFocus: onUnFocus,
onMouseDown: onMouseDown,
onEditorSettings: onEditorSettings,
onEditorTextSizeChanged: onEditorTextSizeChanged,
width: width,
height: height,
onDragEnter: onDragEnter,
),
);
}
}
);
default:
return WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? HtmlExtension.editorStartTags,
direction: AppUtils.getCurrentDirection(context),
onInitial: onInitial,
onChangeContent: onChangeContent,
onFocus: onFocus,
onUnFocus: onUnFocus,
onMouseDown: onMouseDown,
onEditorSettings: onEditorSettings,
onEditorTextSizeChanged: onEditorTextSizeChanged,
width: width,
height: height,
onDragEnter: onDragEnter,
return Semantics(
identifier: ComposerKeyValues.composerContentField,
child: WebEditorWidget(
editorController: editorController,
content: currentWebContent ?? HtmlExtension.editorStartTags,
direction: AppUtils.getCurrentDirection(context),
onInitial: onInitial,
onChangeContent: onChangeContent,
onFocus: onFocus,
onUnFocus: onUnFocus,
onMouseDown: onMouseDown,
onEditorSettings: onEditorSettings,
onEditorTextSizeChanged: onEditorTextSizeChanged,
width: width,
height: height,
onDragEnter: onDragEnter,
),
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'package:model/email/prefix_email_address.dart';
import 'package:model/extensions/email_address_extension.dart';
import 'package:model/mailbox/expand_mode.dart';
import 'package:super_tag_editor/tag_editor.dart';
import 'package:tmail_ui_user/features/base/key_values/composer_key_values.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/prefix_email_address_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart';
Expand Down Expand Up @@ -123,7 +124,9 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
@override
Widget build(BuildContext context) {
return Semantics(
value: 'Composer:${widget.prefix.name}',
identifier: widget.prefix == PrefixEmailAddress.to
? ComposerKeyValues.composerToField
: null,
child: Container(
decoration: const BoxDecoration(
border: Border(
Expand Down
Loading

0 comments on commit 9d2bdb9

Please sign in to comment.