TF-3939 Replace email selection bottom actions to top actions

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-08-05 11:50:14 +07:00
committed by Dat H. Pham
parent 6e86946a1a
commit b7af668d4a
10 changed files with 258 additions and 127 deletions
@@ -1,4 +1,3 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/utils/platform_info.dart';
@@ -8,17 +7,29 @@ import 'package:model/email/presentation_email.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:model/mailbox/select_mode.dart';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/email_selection_action_type.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar/mobile_app_bar_thread_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar/web_app_bar_thread_widget.dart';
typedef OnPopupMenuFilterEmailAction = void Function(FilterMessageOption, RelativeRect);
typedef OnContextMenuFilterEmailAction = void Function(FilterMessageOption);
typedef OnPopupMenuFilterEmailAction = void Function(
FilterMessageOption option,
RelativeRect position,
);
typedef OnContextMenuFilterEmailAction = void Function(
FilterMessageOption option,
);
typedef OnOpenMailboxMenuActionClick = void Function();
typedef OnCancelEditThreadAction = void Function();
typedef OnEmailSelectionAction = void Function(EmailActionType, List<PresentationEmail>);
typedef OnEmailSelectionAction = void Function(
EmailActionType type,
List<PresentationEmail> emails,
);
typedef OnPressEmailSelectionActionClick = void Function(
EmailSelectionActionType type,
List<PresentationEmail> emails,
);
class AppBarThreadWidget extends StatelessWidget {
final ResponsiveUtils responsiveUtils;
final ImagePaths imagePaths;
final OnPopupMenuFilterEmailAction? onPopupMenuFilterEmailAction;
@@ -30,6 +41,7 @@ class AppBarThreadWidget extends StatelessWidget {
final List<PresentationEmail> listEmailSelected;
final SelectMode selectMode;
final FilterMessageOption filterOption;
final OnPressEmailSelectionActionClick? onPressEmailSelectionActionClick;
const AppBarThreadWidget({
Key? key,
@@ -44,6 +56,7 @@ class AppBarThreadWidget extends StatelessWidget {
required this.emailSelectionAction,
this.onPopupMenuFilterEmailAction,
this.onContextMenuFilterEmailAction,
this.onPressEmailSelectionActionClick,
}) : super(key: key);
@override
@@ -76,7 +89,8 @@ class AppBarThreadWidget extends StatelessWidget {
cancelEditThreadAction: cancelEditThreadAction,
onPopupMenuFilterEmailAction: onPopupMenuFilterEmailAction,
onContextMenuFilterEmailAction: onContextMenuFilterEmailAction,
onPressEmailSelectionActionClick: onPressEmailSelectionActionClick,
);
}
}
}
}
@@ -44,8 +44,11 @@ class DefaultMobileAppBarThreadWidget extends StatelessWidget {
return LayoutBuilder(builder: (context, constraints) {
return Container(
color: MobileAppBarThreadWidgetStyle.backgroundColor,
padding: MobileAppBarThreadWidgetStyle.getPadding(context, responsiveUtils),
constraints: const BoxConstraints(minHeight: MobileAppBarThreadWidgetStyle.minHeight),
padding: MobileAppBarThreadWidgetStyle.getPadding(
context,
responsiveUtils,
),
height: MobileAppBarThreadWidgetStyle.height,
child: Row(
children: [
TMailButtonWidget.fromIcon(
@@ -2,15 +2,17 @@ import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:flutter/material.dart';
import 'package:model/email/presentation_email.dart';
import 'package:model/extensions/list_presentation_email_extension.dart';
import 'package:model/extensions/presentation_mailbox_extension.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:model/mailbox/select_mode.dart';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/email_selection_action_type.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar/app_bar_thread_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar/default_mobile_app_bar_thread_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar/selection_mobile_app_bar_thread_widget.dart';
class MobileAppBarThreadWidget extends StatelessWidget {
final ResponsiveUtils responsiveUtils;
final ImagePaths imagePaths;
final PresentationMailbox? mailboxSelected;
@@ -21,6 +23,7 @@ class MobileAppBarThreadWidget extends StatelessWidget {
final OnPopupMenuFilterEmailAction? onPopupMenuFilterEmailAction;
final OnContextMenuFilterEmailAction? onContextMenuFilterEmailAction;
final OnCancelEditThreadAction cancelEditThreadAction;
final OnPressEmailSelectionActionClick? onPressEmailSelectionActionClick;
const MobileAppBarThreadWidget({
super.key,
@@ -34,26 +37,38 @@ class MobileAppBarThreadWidget extends StatelessWidget {
required this.cancelEditThreadAction,
this.onPopupMenuFilterEmailAction,
this.onContextMenuFilterEmailAction,
this.onPressEmailSelectionActionClick,
});
@override
Widget build(BuildContext context) {
if (selectMode == SelectMode.ACTIVE) {
final actionTypes = <EmailSelectionActionType>[
EmailSelectionActionType.selectAll,
if (mailboxSelected?.isArchive != true)
EmailSelectionActionType.archiveMessage,
if (mailboxSelected?.isDeletePermanentlyEnabled == true)
EmailSelectionActionType.deletePermanently
else
EmailSelectionActionType.moveToTrash,
if (listEmailSelected.isAllEmailRead)
EmailSelectionActionType.markAsUnread
else
EmailSelectionActionType.markAsRead,
EmailSelectionActionType.moreAction,
];
return SelectionMobileAppBarThreadWidget(
key: const Key('selection_mobile_app_bar_thread_widget'),
imagePaths: imagePaths,
responsiveUtils: responsiveUtils,
listEmailSelected: listEmailSelected,
mailboxSelected: mailboxSelected,
selectMode: selectMode,
filterOption: filterOption,
selectedEmails: listEmailSelected,
cancelEditThreadAction: cancelEditThreadAction,
onPopupMenuFilterEmailAction: onPopupMenuFilterEmailAction,
onContextMenuFilterEmailAction: onContextMenuFilterEmailAction,
emailSelectionActionTypes: actionTypes,
onPressEmailSelectionActionClick: (type, emails) =>
onPressEmailSelectionActionClick?.call(type, emails),
);
} else {
return DefaultMobileAppBarThreadWidget(
key: const Key('default_mobile_app_bar_thread_widget'),
imagePaths: imagePaths,
responsiveUtils: responsiveUtils,
listEmailSelected: listEmailSelected,
@@ -1,73 +1,79 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter/material.dart';
import 'package:model/email/presentation_email.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:model/mailbox/select_mode.dart';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/email_selection_action_type.dart';
import 'package:tmail_ui_user/features/thread/presentation/styles/app_bar/mobile_app_bar_thread_widget_style.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar/app_bar_thread_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class SelectionMobileAppBarThreadWidget extends StatelessWidget {
final ResponsiveUtils responsiveUtils;
final ImagePaths imagePaths;
final PresentationMailbox? mailboxSelected;
final List<PresentationEmail> listEmailSelected;
final SelectMode selectMode;
final FilterMessageOption filterOption;
final OnPopupMenuFilterEmailAction? onPopupMenuFilterEmailAction;
final OnContextMenuFilterEmailAction? onContextMenuFilterEmailAction;
final List<PresentationEmail> selectedEmails;
final List<EmailSelectionActionType> emailSelectionActionTypes;
final OnPressEmailSelectionActionClick onPressEmailSelectionActionClick;
final OnCancelEditThreadAction cancelEditThreadAction;
const SelectionMobileAppBarThreadWidget({
super.key,
required this.responsiveUtils,
required this.imagePaths,
required this.listEmailSelected,
required this.mailboxSelected,
required this.selectMode,
required this.filterOption,
required this.selectedEmails,
required this.emailSelectionActionTypes,
required this.onPressEmailSelectionActionClick,
required this.cancelEditThreadAction,
this.onPopupMenuFilterEmailAction,
this.onContextMenuFilterEmailAction,
});
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return Container(
color: MobileAppBarThreadWidgetStyle.backgroundColor,
padding: MobileAppBarThreadWidgetStyle.getPadding(context, responsiveUtils),
constraints: const BoxConstraints(minHeight: MobileAppBarThreadWidgetStyle.minHeight),
child: Row(
children: [
TMailButtonWidget(
key: const Key('mobile_cancel_selection_thread_button'),
text: AppLocalizations.of(context).count_email_selected(listEmailSelected.length),
icon: imagePaths.icCancel,
iconColor: MobileAppBarThreadWidgetStyle.backButtonColor,
textStyle: MobileAppBarThreadWidgetStyle.emailCounterTitleStyle,
backgroundColor: Colors.transparent,
onTapActionCallback: cancelEditThreadAction,
),
const Spacer(),
TMailButtonWidget.fromIcon(
key: const Key('mobile_filter_message_button'),
icon: imagePaths.icFilter,
iconColor: MobileAppBarThreadWidgetStyle.getFilterButtonColor(filterOption),
backgroundColor: Colors.transparent,
maxWidth: MobileAppBarThreadWidgetStyle.buttonMaxWidth,
tooltipMessage: AppLocalizations.of(context).filter_messages,
onTapActionCallback: () => onContextMenuFilterEmailAction?.call(filterOption),
onTapActionAtPositionCallback: (position) => onPopupMenuFilterEmailAction?.call(filterOption, position),
),
]
return Container(
color: MobileAppBarThreadWidgetStyle.backgroundColor,
padding: MobileAppBarThreadWidgetStyle.getPadding(
context,
responsiveUtils,
),
height: MobileAppBarThreadWidgetStyle.height,
child: Row(children: [
Expanded(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: TMailButtonWidget(
text: AppLocalizations.of(context).count_email_selected(
selectedEmails.length,
),
icon: imagePaths.icCancel,
iconColor: MobileAppBarThreadWidgetStyle.actionIconColor,
iconSize: MobileAppBarThreadWidgetStyle.actionIconSize,
textStyle:
MobileAppBarThreadWidgetStyle.emailCounterTitleStyle,
backgroundColor: Colors.transparent,
flexibleText: true,
mainAxisSize: MainAxisSize.min,
maxLines: 1,
onTapActionCallback: cancelEditThreadAction,
),
)
],
),
),
);
});
...emailSelectionActionTypes.map(
(type) => TMailButtonWidget.fromIcon(
icon: type.getIcon(imagePaths),
iconColor: type.getIconColor(),
iconSize: type.getIconSize(),
tooltipMessage: type.getTitle(AppLocalizations.of(context)),
backgroundColor: Colors.transparent,
onTapActionCallback: () => onPressEmailSelectionActionClick(
type,
selectedEmails,
),
),
),
]),
);
}
}