From 3457601d14d1716c819159112f6f4c2dcd7887b9 Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 11 Jul 2025 10:43:32 +0700 Subject: [PATCH] Set padding for email address tag in input field Signed-off-by: dab246 --- ...fault_autocomplete_input_field_widget.dart | 50 ++++-- .../default_autocomplete_tag_item_widget.dart | 164 ++++++++++-------- .../draggable_recipient_tag_widget.dart | 4 +- .../email_recovery_form_mobile_builder.dart | 9 +- .../autocomplete_tag_item_web_style.dart | 5 - .../advanced_search_field_widget.dart | 34 ++-- .../advanced_search_input_form.dart | 2 + .../avatar_tag_item_widget.dart | 3 +- 8 files changed, 166 insertions(+), 105 deletions(-) diff --git a/lib/features/base/widget/default_field/default_autocomplete_input_field_widget.dart b/lib/features/base/widget/default_field/default_autocomplete_input_field_widget.dart index a77ac6c06..e6534b4f2 100644 --- a/lib/features/base/widget/default_field/default_autocomplete_input_field_widget.dart +++ b/lib/features/base/widget/default_field/default_autocomplete_input_field_widget.dart @@ -130,18 +130,10 @@ class _DefaultAutocompleteInputFieldWidgetState color: AppColor.m3Tertiary, ), isDense: true, - contentPadding: _currentListEmailAddress.isNotEmpty - ? const EdgeInsetsDirectional.symmetric(vertical: 14) - : const EdgeInsetsDirectional.only( - top: 14, - bottom: 14, - start: 12, - end: 8, - ), + contentPadding: _getTextFieldContentPadding(), ), - padding: _currentListEmailAddress.isNotEmpty - ? const EdgeInsets.symmetric(horizontal: 12) - : EdgeInsets.zero, + padding: _getTagEditorPadding(), + tagSpacing: PlatformInfo.isWeb ? 4.0 : 8.0, borderRadius: 10, borderSize: 1, focusedBorderColor: AppColor.primaryColor, @@ -434,4 +426,40 @@ class _DefaultAutocompleteInputFieldWidgetState setState(onAction); } } + + EdgeInsetsGeometry? _getTextFieldContentPadding() { + if (_currentListEmailAddress.isNotEmpty) { + if (PlatformInfo.isWeb) { + return const EdgeInsetsDirectional.symmetric( + vertical: 14, + horizontal: 4, + ); + } else { + return const EdgeInsetsDirectional.symmetric(vertical: 12); + } + } else { + if (PlatformInfo.isWeb) { + return const EdgeInsetsDirectional.only( + top: 14, + bottom: 14, + start: 12, + end: 8, + ); + } else { + return const EdgeInsetsDirectional.all(12); + } + } + } + + EdgeInsets? _getTagEditorPadding() { + if (_currentListEmailAddress.isNotEmpty) { + if (PlatformInfo.isWeb) { + return const EdgeInsets.symmetric(horizontal: 12); + } else { + return const EdgeInsets.only(left: 12, right: 12, bottom: 9); + } + } else { + return null; + } + } } diff --git a/lib/features/base/widget/default_field/default_autocomplete_tag_item_widget.dart b/lib/features/base/widget/default_field/default_autocomplete_tag_item_widget.dart index a3789b134..df3c8c32f 100644 --- a/lib/features/base/widget/default_field/default_autocomplete_tag_item_widget.dart +++ b/lib/features/base/widget/default_field/default_autocomplete_tag_item_widget.dart @@ -1,7 +1,7 @@ import 'package:core/presentation/extensions/color_extension.dart'; -import 'package:core/presentation/utils/style_utils.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/utils/direction_utils.dart'; +import 'package:core/utils/platform_info.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; @@ -42,78 +42,102 @@ class DefaultAutocompleteTagItemWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return Stack( - alignment: AlignmentDirectional.centerEnd, - children: [ - Padding( - padding: EdgeInsetsDirectional.only( - top: AutoCompleteTagItemWebStyle.paddingTop, - end: isCollapsed ? AutoCompleteTagItemWebStyle.paddingEnd : 0, - ), - child: Draggable( - data: DraggableEmailAddress( - emailAddress: currentEmailAddress, - filterField: field, - ), - feedback: DraggableRecipientTagWidget( - emailAddress: currentEmailAddress, - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), - ), - childWhenDragging: DraggableRecipientTagWidget( - emailAddress: currentEmailAddress, - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), - ), - child: TextFieldTapRegion( - child: InkWell( - onTap: () => isCollapsed - ? onShowFullAction?.call(field) - : null, - child: MouseRegion( - cursor: SystemMouseCursors.grab, - child: Chip( - labelPadding: EdgeInsetsDirectional.symmetric( - horizontal: AutoCompleteTagItemWebStyle.labelPaddingHorizontal, - vertical: DirectionUtils.isDirectionRTLByHasAnyRtl(currentEmailAddress.asString()) ? 0 : 2 - ), - label: Text( - currentEmailAddress.asString(), - maxLines: 1, - overflow: CommonTextStyle.defaultTextOverFlow, - softWrap: CommonTextStyle.defaultSoftWrap, - ), - deleteIcon: SvgPicture.asset( - iconClose, - fit: BoxFit.fill, - ), - padding: EdgeInsets.zero, - labelStyle: AutoCompleteTagItemWebStyle.labelTextStyle, - backgroundColor: _getTagBackgroundColor(), - shape: RoundedRectangleBorder( - borderRadius: AutoCompleteTagItemWebStyle.shapeBorderRadius, - side: _getTagBorderSide(), - ), - avatar: currentEmailAddress.emailAddress.isNotEmpty - ? AvatarTagItemWidget(tagName: currentEmailAddress.emailAddress) - : null, - onDeleted: () => onDeleteTagAction?.call(currentEmailAddress), - ), - ), - ), + Widget bodyWidget = Chip( + labelPadding: EdgeInsetsDirectional.symmetric( + horizontal: AutoCompleteTagItemWebStyle.labelPaddingHorizontal, + vertical: DirectionUtils.isDirectionRTLByHasAnyRtl(currentEmailAddress.asString()) ? 0 : 2, + ), + label: Text( + currentEmailAddress.asString(), + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: AutoCompleteTagItemWebStyle.labelTextStyle, + ), + deleteIcon: SvgPicture.asset(iconClose, fit: BoxFit.fill), + padding: EdgeInsets.zero, + labelStyle: AutoCompleteTagItemWebStyle.labelTextStyle, + backgroundColor: _getTagBackgroundColor(), + shape: RoundedRectangleBorder( + borderRadius: AutoCompleteTagItemWebStyle.shapeBorderRadius, + side: _getTagBorderSide(), + ), + avatar: currentEmailAddress.emailAddress.isNotEmpty + ? AvatarTagItemWidget(tagName: currentEmailAddress.emailAddress) + : null, + onDeleted: () => onDeleteTagAction?.call(currentEmailAddress), + ); + + if (PlatformInfo.isWeb) { + bodyWidget = Draggable( + data: DraggableEmailAddress( + emailAddress: currentEmailAddress, + filterField: field, + ), + feedback: DraggableRecipientTagWidget( + emailAddress: currentEmailAddress, + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), + ), + childWhenDragging: DraggableRecipientTagWidget( + emailAddress: currentEmailAddress, + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), + ), + child: TextFieldTapRegion( + child: InkWell( + onTap: () => isCollapsed ? onShowFullAction?.call(field) : null, + child: MouseRegion( + cursor: SystemMouseCursors.grab, + child: bodyWidget, ), ), ), - if (isCollapsed) - TMailButtonWidget.fromText( - margin: AutoCompleteTagItemWebStyle.marginCollapsed, - text: '+${currentListEmailAddress.length - collapsedListEmailAddress.length}', - onTapActionCallback: () => onShowFullAction?.call(field), - borderRadius: 10, - textStyle: AutoCompleteTagItemWebStyle.collapsedTextStyle, - padding: AutoCompleteTagItemWebStyle.collapsedPadding, - backgroundColor: AutoCompleteTagItemWebStyle.collapsedBackgroundColor, - ) - ], - ); + ); + } else { + bodyWidget = TextFieldTapRegion( + child: InkWell( + onTap: () => isCollapsed ? onShowFullAction?.call(field) : null, + child: bodyWidget, + ), + ); + } + + final listChildrenWidget = [ + if (isCollapsed) + Flexible(child: bodyWidget) + else + bodyWidget, + if (isCollapsed) + TMailButtonWidget.fromText( + margin: const EdgeInsetsDirectional.only(start: 8), + text: '+${currentListEmailAddress.length - collapsedListEmailAddress.length}', + onTapActionCallback: () => onShowFullAction?.call(field), + borderRadius: 10, + alignment: Alignment.center, + textStyle: AutoCompleteTagItemWebStyle.collapsedTextStyle, + padding: PlatformInfo.isWeb + ? const EdgeInsetsDirectional.symmetric(vertical: 4, horizontal: 8) + : const EdgeInsetsDirectional.symmetric(vertical: 6, horizontal: 10), + backgroundColor: AutoCompleteTagItemWebStyle.collapsedBackgroundColor, + ) + ]; + + Widget tagWidget; + if (listChildrenWidget.length == 1) { + tagWidget = listChildrenWidget.first; + } else { + tagWidget = Row( + mainAxisSize: MainAxisSize.min, + children: listChildrenWidget, + ); + } + + if (PlatformInfo.isWeb) { + return Padding( + padding: const EdgeInsetsDirectional.only(top: 3), + child: tagWidget, + ); + } else { + return tagWidget; + } } Color _getTagBackgroundColor() { diff --git a/lib/features/composer/presentation/widgets/draggable_recipient_tag_widget.dart b/lib/features/composer/presentation/widgets/draggable_recipient_tag_widget.dart index ef33de386..a4573699e 100644 --- a/lib/features/composer/presentation/widgets/draggable_recipient_tag_widget.dart +++ b/lib/features/composer/presentation/widgets/draggable_recipient_tag_widget.dart @@ -37,10 +37,10 @@ class DraggableRecipientTagWidget extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ - if (emailAddress.displayName.isNotEmpty) + if (emailAddress.emailAddress.isNotEmpty) GradientCircleAvatarIcon( colors: emailAddress.avatarColors, - label: emailAddress.displayName.firstLetterToUpperCase, + label: emailAddress.emailAddress.firstCharacterToUpperCase, labelFontSize: DraggableRecipientTagWidgetStyle.avatarLabelFontSize, iconSize: DraggableRecipientTagWidgetStyle.avatarIconSize, ), diff --git a/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_mobile_builder.dart b/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_mobile_builder.dart index 0fcc4e79d..a0e631d86 100644 --- a/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_mobile_builder.dart +++ b/lib/features/email_recovery/presentation/widgets/email_recovery_form/email_recovery_form_mobile_builder.dart @@ -161,6 +161,7 @@ class EmailRecoveryFormMobileBuilder extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 17), onChanged: controller.onChangeHasAttachment, )), + const SizedBox(height: 32.0), ], ), ), @@ -170,9 +171,11 @@ class EmailRecoveryFormMobileBuilder extends StatelessWidget { onRestore: () => controller.onRestore(context), nextFocusNode: controller.focusManager.subjectFieldFocusNode, isMobile: true, - padding: const EdgeInsetsDirectional.symmetric( - horizontal: 16, - vertical: 44, + padding: const EdgeInsetsDirectional.only( + start: 16, + end: 16, + top: 12, + bottom: 44, ), ) ], diff --git a/lib/features/mailbox_dashboard/presentation/styles/autocomplete_tag_item_web_style.dart b/lib/features/mailbox_dashboard/presentation/styles/autocomplete_tag_item_web_style.dart index 4e085c0a4..b4cb27430 100644 --- a/lib/features/mailbox_dashboard/presentation/styles/autocomplete_tag_item_web_style.dart +++ b/lib/features/mailbox_dashboard/presentation/styles/autocomplete_tag_item_web_style.dart @@ -3,12 +3,7 @@ import 'package:core/presentation/utils/theme_utils.dart'; import 'package:flutter/material.dart'; class AutoCompleteTagItemWebStyle { - static const double paddingTop = 3.0; - static const double paddingEnd = 40.0; static const double labelPaddingHorizontal = 4.0; - static const EdgeInsetsGeometry collapsedPadding = EdgeInsetsDirectional.symmetric(vertical: 4, horizontal: 8); - - static const EdgeInsetsGeometry marginCollapsed = EdgeInsets.only(top: 3); static const BorderRadius shapeBorderRadius = BorderRadius.all(Radius.circular(10.0)); diff --git a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_field_widget.dart b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_field_widget.dart index e6f3185e4..780f5080a 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_field_widget.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_field_widget.dart @@ -7,29 +7,37 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class AdvancedSearchFieldWidget extends StatelessWidget { final FilterField filterField; final Widget child; + final bool useHeight; const AdvancedSearchFieldWidget({ super.key, required this.filterField, required this.child, + this.useHeight = true, }); @override Widget build(BuildContext context) { - return SizedBox( - height: AdvancedSearchInputFormStyle.inputFieldHeight, - child: Row( - children: [ - SizedBox( - width: AdvancedSearchInputFormStyle.labelMaxWidth, - child: LabelAdvancedSearchFieldWidget( - name: filterField.getTitle(AppLocalizations.of(context)), - ), + final bodyWidget = Row( + children: [ + SizedBox( + width: AdvancedSearchInputFormStyle.labelMaxWidth, + child: LabelAdvancedSearchFieldWidget( + name: filterField.getTitle(AppLocalizations.of(context)), ), - const SizedBox(width: AdvancedSearchInputFormStyle.labelSpace), - Expanded(child: child), - ], - ), + ), + const SizedBox(width: AdvancedSearchInputFormStyle.labelSpace), + Expanded(child: child), + ], ); + + if (useHeight) { + return SizedBox( + height: AdvancedSearchInputFormStyle.inputFieldHeight, + child: bodyWidget, + ); + } else { + return bodyWidget; + } } } diff --git a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart index d8c6168c8..24babdced 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_input_form.dart @@ -23,6 +23,7 @@ class AdvancedSearchInputForm extends GetWidget { children: [ AdvancedSearchFieldWidget( filterField: FilterField.from, + useHeight: false, child: Obx(() => DefaultAutocompleteInputFieldWidget( field: FilterField.from, listEmailAddress: controller.listFromEmailAddress, @@ -44,6 +45,7 @@ class AdvancedSearchInputForm extends GetWidget { const SizedBox(height: 12), AdvancedSearchFieldWidget( filterField: FilterField.to, + useHeight: false, child: Obx(() => DefaultAutocompleteInputFieldWidget( field: FilterField.to, listEmailAddress: controller.listToEmailAddress, diff --git a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/avatar_tag_item_widget.dart b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/avatar_tag_item_widget.dart index e00347971..3f8f68b40 100644 --- a/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/avatar_tag_item_widget.dart +++ b/lib/features/mailbox_dashboard/presentation/widgets/advanced_search/avatar_tag_item_widget.dart @@ -1,5 +1,6 @@ import 'package:collection/collection.dart'; import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/extensions/string_extension.dart'; import 'package:flutter/material.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/styles/avatar_tag_item_style.dart'; @@ -27,7 +28,7 @@ class AvatarTagItemWidget extends StatelessWidget { ) ), child: Text( - tagName.isNotEmpty ? tagName[0].toUpperCase() : '', + tagName.firstCharacterToUpperCase, style: AvatarTagItemStyle.labelTextStyle ) );