TF-3759 Always show dot icon when open popup menu of more action in mailbox view

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-06-16 04:15:30 +07:00
committed by Dat H. Pham
parent b558dd48d1
commit aeaea7b8b2
8 changed files with 148 additions and 97 deletions
@@ -77,7 +77,7 @@ mixin PopupContextMenuActionMixin {
position: position ?? const RelativeRect.fromLTRB(16, 40, 16, 16), position: position ?? const RelativeRect.fromLTRB(16, 40, 16, 16),
color: Colors.white, color: Colors.white,
surfaceTintColor: Colors.white, surfaceTintColor: Colors.white,
menuPadding: const EdgeInsets.only(top: 8, bottom: 8), menuPadding: const EdgeInsets.symmetric(vertical: 8),
elevation: 8, elevation: 8,
shape: const RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(6)), borderRadius: BorderRadius.all(Radius.circular(6)),
@@ -210,7 +210,7 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
onMenuActionClick: PlatformInfo.isMobile onMenuActionClick: PlatformInfo.isMobile
? null ? null
: (position, mailboxNode) { : (position, mailboxNode) {
controller.openMailboxContextMenuAction( return controller.openMailboxContextMenuAction(
context, context,
position, position,
mailboxNode.item, mailboxNode.item,
@@ -64,7 +64,7 @@ extension HandleMailboxActionExtension on MailboxController {
); );
} }
void openMailboxContextMenuAction( Future<void> openMailboxContextMenuAction(
BuildContext context, BuildContext context,
RelativeRect position, RelativeRect position,
PresentationMailbox mailbox, PresentationMailbox mailbox,
@@ -85,9 +85,9 @@ extension HandleMailboxActionExtension on MailboxController {
AppLocalizations.of(context), AppLocalizations.of(context),
); );
if (contextMenuActions.isEmpty) return; if (contextMenuActions.isEmpty) return Future.value();
openBottomSheetContextMenuAction( return openBottomSheetContextMenuAction(
context: context, context: context,
itemActions: contextMenuActions, itemActions: contextMenuActions,
onContextMenuActionClick: (menuAction) => handleMailboxAction( onContextMenuActionClick: (menuAction) => handleMailboxAction(
@@ -106,7 +106,7 @@ extension HandleMailboxActionExtension on MailboxController {
isSubAddressingSupported, isSubAddressingSupported,
); );
if (popupMenuActions.isEmpty) return; if (popupMenuActions.isEmpty) return Future.value();
final popupMenuItems = popupMenuActions.map((menuAction) { final popupMenuItems = popupMenuActions.map((menuAction) {
return PopupMenuItem( return PopupMenuItem(
@@ -121,7 +121,7 @@ extension HandleMailboxActionExtension on MailboxController {
); );
}).toList(); }).toList();
openPopupMenuAction(context, position, popupMenuItems); return openPopupMenuAction(context, position, popupMenuItems);
} }
} }
} }
@@ -5,7 +5,7 @@ import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
typedef OnClickOpenMailboxAction = void Function(PresentationMailbox); typedef OnClickOpenMailboxAction = void Function(PresentationMailbox);
typedef OnClickOpenMenuMailboxAction = void Function(RelativeRect, PresentationMailbox); typedef OnClickOpenMenuMailboxAction = Future<void> Function(RelativeRect, PresentationMailbox);
typedef OnSelectMailboxAction = void Function(PresentationMailbox); typedef OnSelectMailboxAction = void Function(PresentationMailbox);
typedef OnDragEmailToMailboxAccepted = void Function(List<PresentationEmail>, PresentationMailbox); typedef OnDragEmailToMailboxAccepted = void Function(List<PresentationEmail>, PresentationMailbox);
typedef OnLongPressMailboxAction = void Function(PresentationMailbox); typedef OnLongPressMailboxAction = void Function(PresentationMailbox);
@@ -13,7 +13,7 @@ typedef OnLongPressMailboxAction = void Function(PresentationMailbox);
typedef OnClickExpandMailboxNodeAction = void Function(MailboxNode, GlobalKey itemKey); typedef OnClickExpandMailboxNodeAction = void Function(MailboxNode, GlobalKey itemKey);
typedef OnClickOpenMailboxNodeAction = void Function(MailboxNode); typedef OnClickOpenMailboxNodeAction = void Function(MailboxNode);
typedef OnSelectMailboxNodeAction = void Function(MailboxNode); typedef OnSelectMailboxNodeAction = void Function(MailboxNode);
typedef OnClickOpenMenuMailboxNodeAction = void Function(RelativeRect, MailboxNode); typedef OnClickOpenMenuMailboxNodeAction = Future<void> Function(RelativeRect, MailboxNode);
typedef OnLongPressMailboxNodeAction = void Function(MailboxNode); typedef OnLongPressMailboxNodeAction = void Function(MailboxNode);
typedef OnClickSubscribeMailboxAction = void Function(MailboxNode); typedef OnClickSubscribeMailboxAction = void Function(MailboxNode);
typedef OnEmptyMailboxActionCallback = void Function(MailboxNode); typedef OnEmptyMailboxActionCallback = void Function(MailboxNode);
@@ -2,13 +2,16 @@ import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart'; import 'package:core/presentation/utils/theme_utils.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/presentation/views/text/text_overflow_builder.dart'; import 'package:core/presentation/views/text/text_overflow_builder.dart';
import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:model/extensions/presentation_mailbox_extension.dart'; import 'package:model/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/styles/label_mailbox_item_widget_styles.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/styles/label_mailbox_item_widget_styles.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/styles/trailing_mailbox_item_widget_styles.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_method_action_define.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_method_action_define.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/empty_mailbox_popup_dialog_widget.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/empty_mailbox_popup_dialog_widget.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_expand_button.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_expand_button.dart';
@@ -47,6 +50,7 @@ class _LabelMailboxItemWidgetState extends State<LabelMailboxItemWidget> {
final _imagePaths = Get.find<ImagePaths>(); final _imagePaths = Get.find<ImagePaths>();
bool _popupVisible = false; bool _popupVisible = false;
bool _morePopupMenuVisible = false;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -104,7 +108,7 @@ class _LabelMailboxItemWidgetState extends State<LabelMailboxItemWidget> {
responsiveUtils: _responsiveUtils, responsiveUtils: _responsiveUtils,
imagePaths: _imagePaths, imagePaths: _imagePaths,
isItemHovered: widget.isItemHovered, isItemHovered: widget.isItemHovered,
onMenuActionClick: widget.onMenuActionClick, isShowMoreButton: _shouldShowMorePopupMenu,
); );
final childWidget = Row( final childWidget = Row(
@@ -122,6 +126,45 @@ class _LabelMailboxItemWidgetState extends State<LabelMailboxItemWidget> {
onPopupVisibleChange: _onPopupVisibleChange, onPopupVisibleChange: _onPopupVisibleChange,
), ),
), ),
if (_showCleanButton(context) && !_shouldShowMorePopupMenu)
const Padding(
padding: TrailingMailboxItemWidgetStyles.menuIconPadding,
child: SizedBox(width: TrailingMailboxItemWidgetStyles.menuIconSize),
),
if (_showMoreButton(context))
Offstage(
offstage: !_shouldShowMorePopupMenu,
child: TMailButtonWidget.fromIcon(
margin: _responsiveUtils.isDesktop(context) &&
widget.mailboxNode.item.allowedHasEmptyAction
? EdgeInsets.zero
: TrailingMailboxItemWidgetStyles.menuIconMargin,
icon: _imagePaths.icMoreVertical,
iconSize: widget.mailboxNode.item.isTeamMailboxes
? 17
: TrailingMailboxItemWidgetStyles.menuIconSize,
padding: widget.mailboxNode.item.isTeamMailboxes
? const EdgeInsets.all(3)
: TrailingMailboxItemWidgetStyles.menuIconPadding,
backgroundColor: _morePopupMenuVisible
? Theme.of(context).colorScheme.outline.withOpacity(0.08)
: TrailingMailboxItemWidgetStyles.menuIconBackgroundColor,
onTapActionAtPositionCallback: (position) {
if (!_responsiveUtils.isScreenWithShortestSide(context)) {
_onMorePopupMenuVisibleChange(true);
}
widget.onMenuActionClick
?.call(position, widget.mailboxNode)
.whenComplete(() {
if (context.mounted &&
!_responsiveUtils.isScreenWithShortestSide(context)) {
_onMorePopupMenuVisibleChange(false);
}
});
},
),
),
trailingWidget, trailingWidget,
], ],
); );
@@ -153,13 +196,24 @@ class _LabelMailboxItemWidgetState extends State<LabelMailboxItemWidget> {
} }
} }
void _onMorePopupMenuVisibleChange(bool visible) {
if (_morePopupMenuVisible != visible) {
setState(() => _morePopupMenuVisible = visible);
}
}
bool get _shouldShowPopup => widget.isItemHovered || _popupVisible; bool get _shouldShowPopup => widget.isItemHovered || _popupVisible;
bool get _shouldShowMorePopupMenu =>
widget.isItemHovered || _morePopupMenuVisible;
bool _showCleanButton(BuildContext context) { bool _showCleanButton(BuildContext context) {
return _responsiveUtils.isWebDesktop(context) && return _responsiveUtils.isWebDesktop(context) &&
widget.mailboxNode.item.allowedHasEmptyAction; widget.mailboxNode.item.allowedHasEmptyAction;
} }
bool _showMoreButton(BuildContext context) => PlatformInfo.isWeb;
TextStyle get _displayNameTextStyle { TextStyle get _displayNameTextStyle {
if (widget.isSelected) { if (widget.isSelected) {
return ThemeUtils.textStyleInter700( return ThemeUtils.textStyleInter700(
@@ -1,13 +1,11 @@
import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/utils/platform_info.dart'; import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:model/extensions/presentation_mailbox_extension.dart'; import 'package:model/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/styles/trailing_mailbox_item_widget_styles.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/styles/trailing_mailbox_item_widget_styles.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_method_action_define.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/count_of_emails_widget.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/count_of_emails_widget.dart';
class TrailingMailboxItemWidget extends StatelessWidget { class TrailingMailboxItemWidget extends StatelessWidget {
@@ -16,7 +14,7 @@ class TrailingMailboxItemWidget extends StatelessWidget {
final ImagePaths imagePaths; final ImagePaths imagePaths;
final ResponsiveUtils responsiveUtils; final ResponsiveUtils responsiveUtils;
final bool isItemHovered; final bool isItemHovered;
final OnClickOpenMenuMailboxNodeAction? onMenuActionClick; final bool isShowMoreButton;
const TrailingMailboxItemWidget({ const TrailingMailboxItemWidget({
super.key, super.key,
@@ -24,28 +22,14 @@ class TrailingMailboxItemWidget extends StatelessWidget {
required this.imagePaths, required this.imagePaths,
required this.responsiveUtils, required this.responsiveUtils,
this.isItemHovered = false, this.isItemHovered = false,
this.onMenuActionClick, this.isShowMoreButton = false,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (PlatformInfo.isWeb) { if (PlatformInfo.isWeb) {
if (isItemHovered) { if (isShowMoreButton ||
return TMailButtonWidget.fromIcon( responsiveUtils.isDesktop(context) && mailboxNode.item.allowedHasEmptyAction) {
margin: responsiveUtils.isDesktop(context) && mailboxNode.item.allowedHasEmptyAction
? EdgeInsets.zero
: TrailingMailboxItemWidgetStyles.menuIconMargin,
icon: imagePaths.icMoreVertical,
iconSize: mailboxNode.item.isTeamMailboxes
? 17
: TrailingMailboxItemWidgetStyles.menuIconSize,
padding: mailboxNode.item.isTeamMailboxes
? const EdgeInsets.all(3)
: TrailingMailboxItemWidgetStyles.menuIconPadding,
backgroundColor: TrailingMailboxItemWidgetStyles.menuIconBackgroundColor,
onTapActionAtPositionCallback: (position) => onMenuActionClick?.call(position, mailboxNode),
);
} else if (responsiveUtils.isDesktop(context) && mailboxNode.item.allowedHasEmptyAction) {
return const SizedBox(); return const SizedBox();
} else if (mailboxNode.item.allowedToDisplayCountOfUnreadEmails) { } else if (mailboxNode.item.allowedToDisplayCountOfUnreadEmails) {
return Padding( return Padding(
@@ -182,9 +182,7 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
return LayoutBuilder(builder: (context, constraints) { return LayoutBuilder(builder: (context, constraints) {
final mailboxCurrent = controller.listMailboxSearched[index]; final mailboxCurrent = controller.listMailboxSearched[index];
return MailboxSearchedItemBuilder( return MailboxSearchedItemBuilder(
controller.imagePaths, presentationMailbox: mailboxCurrent,
controller.responsiveUtils,
mailboxCurrent,
maxWidth: constraints.maxWidth, maxWidth: constraints.maxWidth,
onDragEmailToMailboxAccepted: controller.dashboardController.dragSelectedMultipleEmailToMailboxAction, onDragEmailToMailboxAccepted: controller.dashboardController.dragSelectedMultipleEmailToMailboxAction,
onClickOpenMailboxAction: (mailbox) => controller.openMailboxAction(context, mailbox), onClickOpenMailboxAction: (mailbox) => controller.openMailboxAction(context, mailbox),
@@ -256,7 +254,7 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
); );
} }
void _openMailboxMenuAction( Future<void> _openMailboxMenuAction(
BuildContext context, BuildContext context,
PresentationMailbox mailbox, PresentationMailbox mailbox,
{RelativeRect? position} {RelativeRect? position}
@@ -280,9 +278,9 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
AppLocalizations.of(context), AppLocalizations.of(context),
); );
if (contextMenuActions.isEmpty) return; if (contextMenuActions.isEmpty) return Future.value();
controller.openBottomSheetContextMenuAction( return controller.openBottomSheetContextMenuAction(
context: context, context: context,
itemActions: contextMenuActions, itemActions: contextMenuActions,
onContextMenuActionClick: (menuAction) => controller.handleMailboxAction( onContextMenuActionClick: (menuAction) => controller.handleMailboxAction(
@@ -301,7 +299,7 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
isSubAddressingSupported, isSubAddressingSupported,
); );
if (popupMenuActions.isEmpty) return; if (popupMenuActions.isEmpty) Future.value();
final popupMenuItems = popupMenuActions.map((menuAction) { final popupMenuItems = popupMenuActions.map((menuAction) {
return PopupMenuItem( return PopupMenuItem(
@@ -320,7 +318,7 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
); );
}).toList(); }).toList();
controller.openPopupMenuAction(context, position, popupMenuItems); return controller.openPopupMenuAction(context, position, popupMenuItems);
} }
} }
} }
@@ -1,6 +1,7 @@
import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/presentation/views/responsive/responsive_widget.dart'; import 'package:core/presentation/views/responsive/responsive_widget.dart';
import 'package:core/presentation/views/text/text_overflow_builder.dart'; import 'package:core/presentation/views/text/text_overflow_builder.dart';
import 'package:core/utils/platform_info.dart'; import 'package:core/utils/platform_info.dart';
@@ -8,6 +9,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:focused_menu_custom/focused_menu.dart'; import 'package:focused_menu_custom/focused_menu.dart';
import 'package:focused_menu_custom/modals.dart'; import 'package:focused_menu_custom/modals.dart';
import 'package:get/get.dart';
import 'package:model/email/presentation_email.dart'; import 'package:model/email/presentation_email.dart';
import 'package:model/extensions/presentation_mailbox_extension.dart'; import 'package:model/extensions/presentation_mailbox_extension.dart';
import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:model/mailbox/presentation_mailbox.dart';
@@ -17,9 +19,7 @@ import 'package:tmail_ui_user/features/search/mailbox/presentation/utils/search_
class MailboxSearchedItemBuilder extends StatefulWidget { class MailboxSearchedItemBuilder extends StatefulWidget {
final PresentationMailbox _presentationMailbox; final PresentationMailbox presentationMailbox;
final ImagePaths _imagePaths;
final ResponsiveUtils _responsiveUtils;
final double? maxWidth; final double? maxWidth;
final OnClickOpenMailboxAction? onClickOpenMailboxAction; final OnClickOpenMailboxAction? onClickOpenMailboxAction;
final OnClickOpenMenuMailboxAction? onClickOpenMenuMailboxAction; final OnClickOpenMenuMailboxAction? onClickOpenMenuMailboxAction;
@@ -27,27 +27,28 @@ class MailboxSearchedItemBuilder extends StatefulWidget {
final OnLongPressMailboxAction? onLongPressMailboxAction; final OnLongPressMailboxAction? onLongPressMailboxAction;
final List<FocusedMenuItem>? listPopupMenuItemAction; final List<FocusedMenuItem>? listPopupMenuItemAction;
const MailboxSearchedItemBuilder( const MailboxSearchedItemBuilder({
this._imagePaths, Key? key,
this._responsiveUtils, required this.presentationMailbox,
this._presentationMailbox, this.maxWidth,
{ this.onClickOpenMailboxAction,
Key? key, this.onClickOpenMenuMailboxAction,
this.maxWidth, this.onDragEmailToMailboxAccepted,
this.onClickOpenMailboxAction, this.onLongPressMailboxAction,
this.onClickOpenMenuMailboxAction, this.listPopupMenuItemAction,
this.onDragEmailToMailboxAccepted, }) : super(key: key);
this.onLongPressMailboxAction,
this.listPopupMenuItemAction
}
) : super(key: key);
@override @override
State<MailboxSearchedItemBuilder> createState() => _MailboxSearchedItemBuilderState(); State<MailboxSearchedItemBuilder> createState() => _MailboxSearchedItemBuilderState();
} }
class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder> { class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder> {
final ImagePaths _imagePaths = Get.find<ImagePaths>();
final ResponsiveUtils _responsiveUtils = Get.find<ResponsiveUtils>();
bool isHoverItem = false; bool isHoverItem = false;
bool _popupMenuVisible = false;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -55,7 +56,7 @@ class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder>
return DragTarget<List<PresentationEmail>>( return DragTarget<List<PresentationEmail>>(
builder: (_, __, ___) => _buildMailboxItem(context), builder: (_, __, ___) => _buildMailboxItem(context),
onAcceptWithDetails: (emails) { onAcceptWithDetails: (emails) {
widget.onDragEmailToMailboxAccepted?.call(emails.data, widget._presentationMailbox); widget.onDragEmailToMailboxAccepted?.call(emails.data, widget.presentationMailbox);
} }
); );
} else { } else {
@@ -76,10 +77,10 @@ class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder>
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
color: getBackgroundColorItem(context) color: getBackgroundColorItem(context)
), ),
padding: SearchMailboxUtils.getPaddingItemListView(context, widget._responsiveUtils), padding: SearchMailboxUtils.getPaddingItemListView(context, _responsiveUtils),
child: Row( child: Row(
crossAxisAlignment: widget._presentationMailbox.mailboxPath?.isNotEmpty == true crossAxisAlignment: widget.presentationMailbox.mailboxPath?.isNotEmpty == true
|| widget._presentationMailbox.isTeamMailboxes || widget.presentationMailbox.isTeamMailboxes
? CrossAxisAlignment.start ? CrossAxisAlignment.start
: CrossAxisAlignment.center, : CrossAxisAlignment.center,
children: [ children: [
@@ -101,7 +102,7 @@ class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder>
); );
} else { } else {
return ResponsiveWidget( return ResponsiveWidget(
responsiveUtils: widget._responsiveUtils, responsiveUtils: _responsiveUtils,
mobile: _buildMailboxItemMobile(), mobile: _buildMailboxItemMobile(),
tablet: _buildMailboxItemTablet() tablet: _buildMailboxItemTablet()
); );
@@ -124,10 +125,10 @@ class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder>
onTap: _onTapMailboxAction, onTap: _onTapMailboxAction,
borderRadius: const BorderRadius.all(Radius.circular(8)), borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Padding( child: Padding(
padding: SearchMailboxUtils.getPaddingItemListView(context, widget._responsiveUtils), padding: SearchMailboxUtils.getPaddingItemListView(context, _responsiveUtils),
child: Row( child: Row(
crossAxisAlignment: widget._presentationMailbox.mailboxPath?.isNotEmpty == true crossAxisAlignment: widget.presentationMailbox.mailboxPath?.isNotEmpty == true
|| widget._presentationMailbox.isTeamMailboxes || widget.presentationMailbox.isTeamMailboxes
? CrossAxisAlignment.start ? CrossAxisAlignment.start
: CrossAxisAlignment.center, : CrossAxisAlignment.center,
children: [ children: [
@@ -158,10 +159,10 @@ class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder>
onLongPress: _onLongPressMailboxAction, onLongPress: _onLongPressMailboxAction,
borderRadius: const BorderRadius.all(Radius.circular(8)), borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Padding( child: Padding(
padding: SearchMailboxUtils.getPaddingItemListView(context, widget._responsiveUtils), padding: SearchMailboxUtils.getPaddingItemListView(context, _responsiveUtils),
child: Row( child: Row(
crossAxisAlignment: widget._presentationMailbox.mailboxPath?.isNotEmpty == true crossAxisAlignment: widget.presentationMailbox.mailboxPath?.isNotEmpty == true
|| widget._presentationMailbox.isTeamMailboxes || widget.presentationMailbox.isTeamMailboxes
? CrossAxisAlignment.start ? CrossAxisAlignment.start
: CrossAxisAlignment.center, : CrossAxisAlignment.center,
children: [ children: [
@@ -184,22 +185,22 @@ class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder>
} }
void _onTapMailboxAction() { void _onTapMailboxAction() {
if (widget._presentationMailbox.allowedToDisplay) { if (widget.presentationMailbox.allowedToDisplay) {
widget.onClickOpenMailboxAction?.call(widget._presentationMailbox); widget.onClickOpenMailboxAction?.call(widget.presentationMailbox);
} }
} }
void _onLongPressMailboxAction() { void _onLongPressMailboxAction() {
if (widget.listPopupMenuItemAction?.isNotEmpty == true) { if (widget.listPopupMenuItemAction?.isNotEmpty == true) {
widget.onLongPressMailboxAction?.call(widget._presentationMailbox); widget.onLongPressMailboxAction?.call(widget.presentationMailbox);
} }
} }
Widget _buildMailboxIcon() { Widget _buildMailboxIcon() {
return SvgPicture.asset( return SvgPicture.asset(
widget._presentationMailbox.allowedToDisplay widget.presentationMailbox.allowedToDisplay
? widget._presentationMailbox.getMailboxIcon(widget._imagePaths) ? widget.presentationMailbox.getMailboxIcon(_imagePaths)
: widget._imagePaths.icHideFolder, : _imagePaths.icHideFolder,
width: 20, width: 20,
height: 20, height: 20,
fit: BoxFit.fill fit: BoxFit.fill
@@ -208,7 +209,7 @@ class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder>
Widget _buildTitleItem(BuildContext context) { Widget _buildTitleItem(BuildContext context) {
return TextOverflowBuilder( return TextOverflowBuilder(
widget._presentationMailbox.getDisplayName(context), widget.presentationMailbox.getDisplayName(context),
style: const TextStyle( style: const TextStyle(
fontSize: 15, fontSize: 15,
color: Colors.black color: Colors.black
@@ -217,18 +218,18 @@ class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder>
} }
Widget _buildSubtitleItem() { Widget _buildSubtitleItem() {
if (widget._presentationMailbox.mailboxPath?.isNotEmpty == true) { if (widget.presentationMailbox.mailboxPath?.isNotEmpty == true) {
return TextOverflowBuilder( return TextOverflowBuilder(
(widget._presentationMailbox.mailboxPath ?? ''), (widget.presentationMailbox.mailboxPath ?? ''),
style: const TextStyle( style: const TextStyle(
fontSize: 11, fontSize: 11,
color: AppColor.colorMailboxPath, color: AppColor.colorMailboxPath,
fontWeight: FontWeight.normal fontWeight: FontWeight.normal
), ),
); );
} else if (widget._presentationMailbox.isTeamMailboxes) { } else if (widget.presentationMailbox.isTeamMailboxes) {
return TextOverflowBuilder( return TextOverflowBuilder(
widget._presentationMailbox.emailTeamMailBoxes, widget.presentationMailbox.emailTeamMailBoxes,
style: const TextStyle( style: const TextStyle(
fontSize: 11, fontSize: 11,
color: AppColor.colorEmailAddressFull, color: AppColor.colorEmailAddressFull,
@@ -241,25 +242,29 @@ class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder>
} }
Widget _buildMenuIcon(BuildContext context) { Widget _buildMenuIcon(BuildContext context) {
if (isHoverItem && widget.listPopupMenuItemAction?.isNotEmpty == true) { if (widget.listPopupMenuItemAction?.isNotEmpty == true) {
return InkWell( return Offstage(
onTapDown: (detail) { offstage: !_shouldShowPopupMenu,
final screenSize = MediaQuery.of(context).size; child: TMailButtonWidget.fromIcon(
final offset = detail.globalPosition; icon: _imagePaths.icMoreVertical,
final position = RelativeRect.fromLTRB( backgroundColor: _popupMenuVisible
offset.dx, ? Theme.of(context).colorScheme.outline.withOpacity(0.08)
offset.dy, : Colors.transparent,
screenSize.width - offset.dx, iconSize: 16,
screenSize.height - offset.dy, padding: const EdgeInsetsDirectional.all(2),
); onTapActionAtPositionCallback: (position) {
widget.onClickOpenMenuMailboxAction?.call(position, widget._presentationMailbox); if (!_responsiveUtils.isScreenWithShortestSide(context)) {
}, _onPopupMenuVisibleChange(true);
child: SvgPicture.asset( }
widget._imagePaths.icComposerMenu, widget.onClickOpenMenuMailboxAction
width: 20, ?.call(position, widget.presentationMailbox)
height: 20, .whenComplete(() {
fit: BoxFit.fill if (context.mounted && !_responsiveUtils.isScreenWithShortestSide(context)) {
) _onPopupMenuVisibleChange(false);
}
});
},
),
); );
} else { } else {
return const SizedBox.shrink(); return const SizedBox.shrink();
@@ -270,9 +275,19 @@ class _MailboxSearchedItemBuilderState extends State<MailboxSearchedItemBuilder>
if (isHoverItem) { if (isHoverItem) {
return AppColor.colorBgMailboxSelected; return AppColor.colorBgMailboxSelected;
} else { } else {
return widget._responsiveUtils.isDesktop(context) return _responsiveUtils.isDesktop(context)
? AppColor.colorBgDesktop ? AppColor.colorBgDesktop
: Colors.transparent; : Colors.transparent;
} }
} }
bool get _shouldShowPopupMenu =>
(isHoverItem && widget.listPopupMenuItemAction?.isNotEmpty == true) ||
_popupMenuVisible;
void _onPopupMenuVisibleChange(bool visible) {
if (_popupMenuVisible != visible) {
setState(() => _popupMenuVisible = visible);
}
}
} }