TF-3766 Change context menu style for mailbox on mobile
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -91,7 +91,6 @@ export 'presentation/views/popup_menu/popup_menu_item_widget.dart';
|
|||||||
export 'presentation/views/quick_search/quick_search_input_form.dart';
|
export 'presentation/views/quick_search/quick_search_input_form.dart';
|
||||||
export 'presentation/views/toast/toast_position.dart';
|
export 'presentation/views/toast/toast_position.dart';
|
||||||
export 'presentation/views/toast/tmail_toast.dart';
|
export 'presentation/views/toast/tmail_toast.dart';
|
||||||
export 'presentation/views/bottom_popup/full_screen_action_sheet_builder.dart';
|
|
||||||
export 'presentation/views/checkbox/labeled_checkbox.dart';
|
export 'presentation/views/checkbox/labeled_checkbox.dart';
|
||||||
export 'presentation/views/checkbox/default_labeled_checkbox.dart';
|
export 'presentation/views/checkbox/default_labeled_checkbox.dart';
|
||||||
export 'presentation/views/checkbox/custom_icon_labeled_checkbox.dart';
|
export 'presentation/views/checkbox/custom_icon_labeled_checkbox.dart';
|
||||||
|
|||||||
@@ -243,6 +243,15 @@ class ThemeUtils {
|
|||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static final TextStyle textStyleInter400 = TextStyle(
|
||||||
|
fontFamily: ConstantsUI.fontApp,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
letterSpacing: -0.15,
|
||||||
|
fontSize: 16,
|
||||||
|
height: 21.01 / 16,
|
||||||
|
color: AppColor.gray424244.withOpacity(0.9),
|
||||||
|
);
|
||||||
|
|
||||||
static TextStyle textStyleM3LabelLarge({Color? color}) => TextStyle(
|
static TextStyle textStyleM3LabelLarge({Color? color}) => TextStyle(
|
||||||
fontFamily: ConstantsUI.fontApp,
|
fontFamily: ConstantsUI.fontApp,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
import 'package:core/core.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
|
||||||
|
|
||||||
typedef OnCloseActionClick = Function();
|
|
||||||
|
|
||||||
class FullScreenActionSheetBuilder {
|
|
||||||
final BuildContext context;
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
final Widget? titleWidget;
|
|
||||||
final Widget? cancelWidget;
|
|
||||||
OnCloseActionClick? onCloseActionClick;
|
|
||||||
late double _statusBarHeight;
|
|
||||||
|
|
||||||
FullScreenActionSheetBuilder({
|
|
||||||
required this.context,
|
|
||||||
required this.child,
|
|
||||||
this.titleWidget,
|
|
||||||
this.cancelWidget,
|
|
||||||
this.onCloseActionClick,
|
|
||||||
}) {
|
|
||||||
_statusBarHeight = MediaQuery.of(context).padding.top;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future show() {
|
|
||||||
return showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
enableDrag: false,
|
|
||||||
builder: (context) => PointerInterceptor(child: _buildBody(context)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildBody(BuildContext context) {
|
|
||||||
return SafeArea(
|
|
||||||
top: true,
|
|
||||||
bottom: false,
|
|
||||||
left: false,
|
|
||||||
right: false,
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.only(top: _statusBarHeight),
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: const BorderRadius.only(
|
|
||||||
topRight: Radius.circular(14),
|
|
||||||
topLeft: Radius.circular(14),
|
|
||||||
),
|
|
||||||
child: Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
leading: const SizedBox.shrink(),
|
|
||||||
title: titleWidget,
|
|
||||||
centerTitle: true,
|
|
||||||
actions: [
|
|
||||||
GestureDetector(
|
|
||||||
child: cancelWidget,
|
|
||||||
onTapDown: (_) {
|
|
||||||
onCloseActionClick?.call();
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: child,
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
|
|
||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/presentation/views/bottom_popup/cupertino_action_sheet_builder.dart';
|
|
||||||
import 'package:core/utils/platform_info.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_dialog_view.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_item_action.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||||
|
|
||||||
@@ -15,12 +16,34 @@ mixin PopupContextMenuActionMixin {
|
|||||||
{
|
{
|
||||||
Widget? cancelButton,
|
Widget? cancelButton,
|
||||||
Key? key,
|
Key? key,
|
||||||
|
List<ContextMenuItemAction>? itemActions,
|
||||||
|
OnContextMenuActionClick? onContextMenuActionClick,
|
||||||
}
|
}
|
||||||
) async {
|
) async {
|
||||||
await (CupertinoActionSheetBuilder(context, key: key)
|
await showModalBottomSheet(
|
||||||
..addTiles(actionTiles)
|
context: context,
|
||||||
..addCancelButton(cancelButton ?? buildCancelButton(context)))
|
showDragHandle: true,
|
||||||
.show();
|
useSafeArea: true,
|
||||||
|
isScrollControlled: true,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(16.0),
|
||||||
|
topRight: Radius.circular(16.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
barrierColor: Colors.black.withOpacity(0.2),
|
||||||
|
builder: (_) {
|
||||||
|
return ColoredBox(
|
||||||
|
color: Colors.white,
|
||||||
|
child: ContextMenuDialogView(
|
||||||
|
actions: itemActions ?? [],
|
||||||
|
onContextMenuActionClick: (menuAction) =>
|
||||||
|
onContextMenuActionClick?.call(menuAction),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void openPopupMenuAction(
|
void openPopupMenuAction(
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
|
import 'package:core/presentation/utils/theme_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_item_action.dart';
|
||||||
|
|
||||||
|
class ContextMenuDialogItem extends StatelessWidget {
|
||||||
|
final ContextMenuItemAction menuAction;
|
||||||
|
final OnContextMenuActionClick onContextMenuActionClick;
|
||||||
|
|
||||||
|
const ContextMenuDialogItem({
|
||||||
|
super.key,
|
||||||
|
required this.menuAction,
|
||||||
|
required this.onContextMenuActionClick,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Material(
|
||||||
|
type: MaterialType.transparency,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => menuAction.onClick(onContextMenuActionClick),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 48,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Container(
|
||||||
|
height: 32,
|
||||||
|
width: 32,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
menuAction.actionIcon,
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
colorFilter: menuAction.actionIconColor.asFilter(),
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
menuAction.actionName,
|
||||||
|
style: ThemeUtils.textStyleInter400.copyWith(
|
||||||
|
color: menuAction.actionNameColor,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_dialog_item.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_item_action.dart';
|
||||||
|
|
||||||
|
class ContextMenuDialogView extends StatelessWidget {
|
||||||
|
final List<ContextMenuItemAction> actions;
|
||||||
|
final OnContextMenuActionClick onContextMenuActionClick;
|
||||||
|
|
||||||
|
const ContextMenuDialogView({
|
||||||
|
super.key,
|
||||||
|
required this.actions,
|
||||||
|
required this.onContextMenuActionClick,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: actions.map((menuAction) => ContextMenuDialogItem(
|
||||||
|
menuAction: menuAction,
|
||||||
|
onContextMenuActionClick: onContextMenuActionClick,
|
||||||
|
)).toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
typedef OnContextMenuActionClick = void Function(ContextMenuItemAction action);
|
||||||
|
|
||||||
|
abstract class ContextMenuItemAction<T> with EquatableMixin {
|
||||||
|
final T action;
|
||||||
|
|
||||||
|
ContextMenuItemAction(this.action);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [action];
|
||||||
|
|
||||||
|
String get actionIcon;
|
||||||
|
|
||||||
|
Color get actionIconColor => AppColor.gray424244.withOpacity(0.72);
|
||||||
|
|
||||||
|
String get actionName;
|
||||||
|
|
||||||
|
Color get actionNameColor => AppColor.gray424244.withOpacity(0.9);
|
||||||
|
|
||||||
|
void onClick(OnContextMenuActionClick callback) => callback(this);
|
||||||
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
|
||||||
|
|
||||||
abstract class ContextMenuItemAction<T> with EquatableMixin {
|
|
||||||
final T action;
|
|
||||||
final ContextMenuItemState state;
|
|
||||||
|
|
||||||
ContextMenuItemAction(this.action, this.state);
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object?> get props => [action, state];
|
|
||||||
|
|
||||||
bool get isActivated => state == ContextMenuItemState.activated;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ContextMenuItemState {
|
|
||||||
activated,
|
|
||||||
deactivated
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,20 @@
|
|||||||
|
|
||||||
import 'package:core/core.dart';
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
|
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||||
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||||
|
import 'package:model/mailbox/mailbox_constants.dart';
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart';
|
import 'package:tmail_ui_user/features/base/widget/popup_item_widget.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/context_item_mailbox_action.dart';
|
import 'package:tmail_ui_user/features/mailbox/presentation/model/context_item_mailbox_action.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_bottom_sheet_action_tile_builder.dart';
|
import 'package:tmail_ui_user/features/mailbox/presentation/utils/mailbox_utils.dart';
|
||||||
|
import 'package:tmail_ui_user/main/error/capability_validator.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
mixin MailboxWidgetMixin {
|
mixin MailboxWidgetMixin {
|
||||||
|
|
||||||
@@ -100,54 +108,43 @@ mixin MailboxWidgetMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> contextMenuMailboxActionTiles(
|
void openMailboxMenuActionOnMobile(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
ImagePaths imagePaths,
|
ImagePaths imagePaths,
|
||||||
PresentationMailbox mailbox,
|
PresentationMailbox mailbox,
|
||||||
List<ContextMenuItemMailboxAction> contextMenuActions,
|
MailboxController controller
|
||||||
{
|
|
||||||
required Function(BuildContext, MailboxActions, PresentationMailbox) handleMailboxAction
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
return contextMenuActions
|
final bool deletedMessageVaultSupported = MailboxUtils.isDeletedMessageVaultSupported(
|
||||||
.map((action) => _buildContextMenuActionTile(
|
controller.mailboxDashBoardController.sessionCurrent,
|
||||||
context,
|
controller.mailboxDashBoardController.accountId.value);
|
||||||
imagePaths,
|
|
||||||
action,
|
|
||||||
mailbox,
|
|
||||||
handleMailboxAction: handleMailboxAction
|
|
||||||
))
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildContextMenuActionTile(
|
final bool subaddressingSupported = isSubaddressingSupported(
|
||||||
BuildContext context,
|
controller.mailboxDashBoardController.sessionCurrent,
|
||||||
ImagePaths imagePaths,
|
controller.mailboxDashBoardController.accountId.value);
|
||||||
ContextMenuItemMailboxAction contextMenuItem,
|
|
||||||
PresentationMailbox mailbox,
|
final contextMenuActions = listContextMenuItemAction(
|
||||||
{
|
mailbox,
|
||||||
required Function(BuildContext, MailboxActions, PresentationMailbox) handleMailboxAction
|
controller.mailboxDashBoardController.enableSpamReport,
|
||||||
|
deletedMessageVaultSupported,
|
||||||
|
subaddressingSupported,
|
||||||
|
imagePaths,
|
||||||
|
AppLocalizations.of(context),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (contextMenuActions.isEmpty) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
) {
|
|
||||||
return (MailboxBottomSheetActionTileBuilder(
|
controller.openContextMenuAction(
|
||||||
Key('${contextMenuItem.action.name}_action'),
|
context,
|
||||||
SvgPicture.asset(
|
[],
|
||||||
contextMenuItem.action.getContextMenuIcon(imagePaths),
|
itemActions: contextMenuActions,
|
||||||
colorFilter: contextMenuItem.action.getColorContextMenuIcon().asFilter(),
|
onContextMenuActionClick: (menuAction) => controller.handleMailboxAction(
|
||||||
width: 24,
|
context,
|
||||||
height: 24
|
menuAction.action,
|
||||||
),
|
mailbox,
|
||||||
contextMenuItem.action.getTitleContextMenu(context),
|
),
|
||||||
mailbox,
|
);
|
||||||
absorbing: !contextMenuItem.isActivated,
|
|
||||||
opacity: !contextMenuItem.isActivated)
|
|
||||||
..actionTextStyle(textStyle: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
color: contextMenuItem.action.getColorContextMenuTitle(),
|
|
||||||
fontWeight: FontWeight.w500
|
|
||||||
))
|
|
||||||
..onActionClick((mailbox) => handleMailboxAction(context, contextMenuItem.action, mailbox))
|
|
||||||
).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ContextMenuItemMailboxAction> listContextMenuItemAction(
|
List<ContextMenuItemMailboxAction> listContextMenuItemAction(
|
||||||
@@ -155,16 +152,77 @@ mixin MailboxWidgetMixin {
|
|||||||
bool spamReportEnabled,
|
bool spamReportEnabled,
|
||||||
bool deletedMessageVaultSupported,
|
bool deletedMessageVaultSupported,
|
||||||
bool subaddressingSupported,
|
bool subaddressingSupported,
|
||||||
|
ImagePaths imagePaths,
|
||||||
|
AppLocalizations appLocalizations,
|
||||||
) {
|
) {
|
||||||
final mailboxActionsSupported = _listActionForAllMailboxType(mailbox, spamReportEnabled, deletedMessageVaultSupported, subaddressingSupported);
|
final mailboxActionsSupported = _listActionForAllMailboxType(mailbox, spamReportEnabled, deletedMessageVaultSupported, subaddressingSupported);
|
||||||
|
|
||||||
final listContextMenuItemAction = mailboxActionsSupported
|
final listContextMenuItemAction = mailboxActionsSupported
|
||||||
.map((action) => ContextMenuItemMailboxAction(action, action.getContextMenuItemState(mailbox)))
|
.map((action) => ContextMenuItemMailboxAction(
|
||||||
|
action,
|
||||||
|
appLocalizations,
|
||||||
|
imagePaths
|
||||||
|
))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return listContextMenuItemAction;
|
return listContextMenuItemAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void openMailboxMenuActionOnWeb(
|
||||||
|
BuildContext context,
|
||||||
|
ImagePaths imagePaths,
|
||||||
|
ResponsiveUtils responsiveUtils,
|
||||||
|
RelativeRect position,
|
||||||
|
PresentationMailbox mailbox,
|
||||||
|
MailboxController controller
|
||||||
|
) {
|
||||||
|
final bool deletedMessageVaultSupported = MailboxUtils.isDeletedMessageVaultSupported(
|
||||||
|
controller.mailboxDashBoardController.sessionCurrent,
|
||||||
|
controller.mailboxDashBoardController.accountId.value);
|
||||||
|
|
||||||
|
final bool subaddressingSupported = isSubaddressingSupported(
|
||||||
|
controller.mailboxDashBoardController.sessionCurrent,
|
||||||
|
controller.mailboxDashBoardController.accountId.value);
|
||||||
|
|
||||||
|
final contextMenuActions = listContextMenuItemAction(
|
||||||
|
mailbox,
|
||||||
|
controller.mailboxDashBoardController.enableSpamReport,
|
||||||
|
deletedMessageVaultSupported,
|
||||||
|
subaddressingSupported,
|
||||||
|
imagePaths,
|
||||||
|
AppLocalizations.of(context),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (contextMenuActions.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responsiveUtils.isScreenWithShortestSide(context)) {
|
||||||
|
controller.openContextMenuAction(
|
||||||
|
context,
|
||||||
|
[],
|
||||||
|
itemActions: contextMenuActions,
|
||||||
|
onContextMenuActionClick: (menuAction) => controller.handleMailboxAction(
|
||||||
|
context,
|
||||||
|
menuAction.action,
|
||||||
|
mailbox,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
controller.openPopupMenuAction(
|
||||||
|
context,
|
||||||
|
position,
|
||||||
|
popupMenuMailboxActionTiles(
|
||||||
|
context,
|
||||||
|
imagePaths,
|
||||||
|
mailbox,
|
||||||
|
contextMenuActions,
|
||||||
|
handleMailboxAction: controller.handleMailboxAction
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<PopupMenuEntry> popupMenuMailboxActionTiles(
|
List<PopupMenuEntry> popupMenuMailboxActionTiles(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
ImagePaths imagePaths,
|
ImagePaths imagePaths,
|
||||||
@@ -185,6 +243,20 @@ mixin MailboxWidgetMixin {
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isSubaddressingSupported(Session? session, AccountId? accountId) {
|
||||||
|
if (session == null || accountId == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!CapabilityIdentifier.jmapTeamMailboxes.isSupported(session, accountId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (session.getCapabilityProperties(accountId, CapabilityIdentifier.jmapTeamMailboxes)
|
||||||
|
?.props[0] as Map<String, dynamic>?)
|
||||||
|
?[subaddressingSupported]
|
||||||
|
?? false;
|
||||||
|
}
|
||||||
|
|
||||||
PopupMenuItem _buildPopupMenuItem(
|
PopupMenuItem _buildPopupMenuItem(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
ImagePaths imagePaths,
|
ImagePaths imagePaths,
|
||||||
@@ -196,21 +268,15 @@ mixin MailboxWidgetMixin {
|
|||||||
) {
|
) {
|
||||||
return PopupMenuItem(
|
return PopupMenuItem(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
child: AbsorbPointer(
|
child: PopupItemWidget(
|
||||||
absorbing: !contextMenuItem.isActivated,
|
iconAction: contextMenuItem.action.getContextMenuIcon(imagePaths),
|
||||||
child: Opacity(
|
nameAction: contextMenuItem.action.getTitleContextMenu(AppLocalizations.of(context)),
|
||||||
opacity: contextMenuItem.isActivated ? 1.0 : 0.3,
|
colorIcon: contextMenuItem.action.getPopupMenuIconColor(),
|
||||||
child: PopupItemWidget(
|
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
|
||||||
iconAction: contextMenuItem.action.getContextMenuIcon(imagePaths),
|
styleName: ThemeUtils.textStyleBodyBody3(
|
||||||
nameAction: contextMenuItem.action.getTitleContextMenu(context),
|
color: contextMenuItem.action.getPopupMenuTitleColor()
|
||||||
colorIcon: contextMenuItem.action.getColorContextMenuIcon(),
|
|
||||||
padding: const EdgeInsetsDirectional.symmetric(horizontal: 12),
|
|
||||||
styleName: ThemeUtils.textStyleBodyBody3(
|
|
||||||
color: contextMenuItem.action.getColorContextMenuTitle()
|
|
||||||
),
|
|
||||||
onCallbackAction: () => handleMailboxAction(context, contextMenuItem.action, mailbox)
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
onCallbackAction: () => handleMailboxAction(context, contextMenuItem.action, mailbox)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,29 @@
|
|||||||
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
import 'package:tmail_ui_user/features/base/widget/context_menu_item_action.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_item_action.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
class ContextMenuItemMailboxAction extends ContextMenuItemAction<MailboxActions> {
|
class ContextMenuItemMailboxAction
|
||||||
ContextMenuItemMailboxAction(super.action, super.state);
|
extends ContextMenuItemAction<MailboxActions> {
|
||||||
|
final AppLocalizations appLocalizations;
|
||||||
|
final ImagePaths imagePaths;
|
||||||
|
|
||||||
|
ContextMenuItemMailboxAction(
|
||||||
|
super.action,
|
||||||
|
this.appLocalizations,
|
||||||
|
this.imagePaths,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get actionIcon => action.getContextMenuIcon(imagePaths);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get actionName => action.getTitleContextMenu(appLocalizations);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color get actionIconColor => action.getContextMenuIconColor();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color get actionNameColor => action.getContextMenuIconColor();
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/core.dart';
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:model/extensions/presentation_mailbox_extension.dart';
|
|
||||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
|
||||||
import 'package:tmail_ui_user/features/base/widget/context_menu_item_action.dart';
|
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
enum MailboxActions {
|
enum MailboxActions {
|
||||||
@@ -48,44 +45,44 @@ extension MailboxActionsExtension on MailboxActions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getTitleContextMenu(BuildContext context) {
|
String getTitleContextMenu(AppLocalizations appLocalizations) {
|
||||||
switch(this) {
|
switch(this) {
|
||||||
case MailboxActions.openInNewTab:
|
case MailboxActions.openInNewTab:
|
||||||
return AppLocalizations.of(context).openInNewTab;
|
return appLocalizations.openInNewTab;
|
||||||
case MailboxActions.copySubaddress:
|
case MailboxActions.copySubaddress:
|
||||||
return AppLocalizations.of(context).copySubaddress;
|
return appLocalizations.copySubaddress;
|
||||||
case MailboxActions.newSubfolder:
|
case MailboxActions.newSubfolder:
|
||||||
return AppLocalizations.of(context).newSubfolder;
|
return appLocalizations.newSubfolder;
|
||||||
case MailboxActions.createFilter:
|
case MailboxActions.createFilter:
|
||||||
return AppLocalizations.of(context).createFilter;
|
return appLocalizations.createFilter;
|
||||||
case MailboxActions.disableSpamReport:
|
case MailboxActions.disableSpamReport:
|
||||||
return AppLocalizations.of(context).disableSpamReport;
|
return appLocalizations.disableSpamReport;
|
||||||
case MailboxActions.enableSpamReport:
|
case MailboxActions.enableSpamReport:
|
||||||
return AppLocalizations.of(context).enableSpamReport;
|
return appLocalizations.enableSpamReport;
|
||||||
case MailboxActions.markAsRead:
|
case MailboxActions.markAsRead:
|
||||||
return AppLocalizations.of(context).mark_as_read;
|
return appLocalizations.mark_as_read;
|
||||||
case MailboxActions.move:
|
case MailboxActions.move:
|
||||||
return AppLocalizations.of(context).moveFolder;
|
return appLocalizations.moveFolder;
|
||||||
case MailboxActions.rename:
|
case MailboxActions.rename:
|
||||||
return AppLocalizations.of(context).renameFolder;
|
return appLocalizations.renameFolder;
|
||||||
case MailboxActions.delete:
|
case MailboxActions.delete:
|
||||||
return AppLocalizations.of(context).deleteFolder;
|
return appLocalizations.deleteFolder;
|
||||||
case MailboxActions.disableMailbox:
|
case MailboxActions.disableMailbox:
|
||||||
return AppLocalizations.of(context).hideFolder;
|
return appLocalizations.hideFolder;
|
||||||
case MailboxActions.enableMailbox:
|
case MailboxActions.enableMailbox:
|
||||||
return AppLocalizations.of(context).showFolder;
|
return appLocalizations.showFolder;
|
||||||
case MailboxActions.emptyTrash:
|
case MailboxActions.emptyTrash:
|
||||||
return AppLocalizations.of(context).emptyTrash;
|
return appLocalizations.emptyTrash;
|
||||||
case MailboxActions.emptySpam:
|
case MailboxActions.emptySpam:
|
||||||
return AppLocalizations.of(context).deleteAllSpamEmails;
|
return appLocalizations.deleteAllSpamEmails;
|
||||||
case MailboxActions.confirmMailSpam:
|
case MailboxActions.confirmMailSpam:
|
||||||
return AppLocalizations.of(context).confirmAllEmailHereAreSpam;
|
return appLocalizations.confirmAllEmailHereAreSpam;
|
||||||
case MailboxActions.recoverDeletedMessages:
|
case MailboxActions.recoverDeletedMessages:
|
||||||
return AppLocalizations.of(context).recoverDeletedMessages;
|
return appLocalizations.recoverDeletedMessages;
|
||||||
case MailboxActions.allowSubaddressing:
|
case MailboxActions.allowSubaddressing:
|
||||||
return AppLocalizations.of(context).allowSubaddressing;
|
return appLocalizations.allowSubaddressing;
|
||||||
case MailboxActions.disallowSubaddressing:
|
case MailboxActions.disallowSubaddressing:
|
||||||
return AppLocalizations.of(context).disallowSubaddressing;
|
return appLocalizations.disallowSubaddressing;
|
||||||
default:
|
default:
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -134,7 +131,7 @@ extension MailboxActionsExtension on MailboxActions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Color getColorContextMenuTitle() {
|
Color getPopupMenuTitleColor() {
|
||||||
switch(this) {
|
switch(this) {
|
||||||
case MailboxActions.delete:
|
case MailboxActions.delete:
|
||||||
return AppColor.redFF3347;
|
return AppColor.redFF3347;
|
||||||
@@ -143,7 +140,7 @@ extension MailboxActionsExtension on MailboxActions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Color getColorContextMenuIcon() {
|
Color getPopupMenuIconColor() {
|
||||||
switch(this) {
|
switch(this) {
|
||||||
case MailboxActions.delete:
|
case MailboxActions.delete:
|
||||||
return AppColor.redFF3347;
|
return AppColor.redFF3347;
|
||||||
@@ -152,6 +149,24 @@ extension MailboxActionsExtension on MailboxActions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color getContextMenuIconColor() {
|
||||||
|
switch (this) {
|
||||||
|
case MailboxActions.delete:
|
||||||
|
return AppColor.redFF3347;
|
||||||
|
default:
|
||||||
|
return AppColor.gray424244.withOpacity(0.72);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color getContextMenuTitleColor() {
|
||||||
|
switch (this) {
|
||||||
|
case MailboxActions.delete:
|
||||||
|
return AppColor.redFF3347;
|
||||||
|
default:
|
||||||
|
return AppColor.gray424244.withOpacity(0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool canSearch() {
|
bool canSearch() {
|
||||||
switch(this) {
|
switch(this) {
|
||||||
case MailboxActions.create:
|
case MailboxActions.create:
|
||||||
@@ -187,33 +202,4 @@ extension MailboxActionsExtension on MailboxActions {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextMenuItemState getContextMenuItemState(PresentationMailbox mailbox) {
|
|
||||||
switch(this) {
|
|
||||||
case MailboxActions.openInNewTab:
|
|
||||||
case MailboxActions.copySubaddress:
|
|
||||||
case MailboxActions.newSubfolder:
|
|
||||||
case MailboxActions.createFilter:
|
|
||||||
case MailboxActions.disableSpamReport:
|
|
||||||
case MailboxActions.enableSpamReport:
|
|
||||||
case MailboxActions.enableMailbox:
|
|
||||||
case MailboxActions.disableMailbox:
|
|
||||||
case MailboxActions.move:
|
|
||||||
case MailboxActions.rename:
|
|
||||||
case MailboxActions.delete:
|
|
||||||
case MailboxActions.emptyTrash:
|
|
||||||
case MailboxActions.emptySpam:
|
|
||||||
case MailboxActions.confirmMailSpam:
|
|
||||||
case MailboxActions.recoverDeletedMessages:
|
|
||||||
case MailboxActions.allowSubaddressing:
|
|
||||||
case MailboxActions.disallowSubaddressing:
|
|
||||||
return ContextMenuItemState.activated;
|
|
||||||
case MailboxActions.markAsRead:
|
|
||||||
return mailbox.countUnReadEmailsAsString.isNotEmpty
|
|
||||||
? ContextMenuItemState.activated
|
|
||||||
: ContextMenuItemState.deactivated;
|
|
||||||
default:
|
|
||||||
return ContextMenuItemState.deactivated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
typedef OnMailboxActionsClick = void Function(MailboxActions, List<PresentationMailbox>);
|
typedef OnMailboxActionsClick = void Function(MailboxActions, List<PresentationMailbox>);
|
||||||
|
|
||||||
@@ -44,12 +45,12 @@ class BottomBarSelectionMailboxWidget extends StatelessWidget {
|
|||||||
key: Key('${action.name}_button'),
|
key: Key('${action.name}_button'),
|
||||||
text: responsiveUtils.isLandscapeMobile(context)
|
text: responsiveUtils.isLandscapeMobile(context)
|
||||||
? ''
|
? ''
|
||||||
: action.getTitleContextMenu(context),
|
: action.getTitleContextMenu(AppLocalizations.of(context)),
|
||||||
icon: action.getContextMenuIcon(imagePaths),
|
icon: action.getContextMenuIcon(imagePaths),
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
flexibleText: true,
|
flexibleText: true,
|
||||||
tooltipMessage: action.getTitleContextMenu(context),
|
tooltipMessage: action.getTitleContextMenu(AppLocalizations.of(context)),
|
||||||
textStyle: const TextStyle(fontSize: 12, color: AppColor.colorTextButton),
|
textStyle: const TextStyle(fontSize: 12, color: AppColor.colorTextButton),
|
||||||
onTapActionCallback: () => onMailboxActionsClick.call(action, _listSelectionMailbox),
|
onTapActionCallback: () => onMailboxActionsClick.call(action, _listSelectionMailbox),
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -211,6 +211,8 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
|
|||||||
controller.dashboardController.enableSpamReport,
|
controller.dashboardController.enableSpamReport,
|
||||||
deletedMessageVaultSupported,
|
deletedMessageVaultSupported,
|
||||||
isSubAddressingSupported,
|
isSubAddressingSupported,
|
||||||
|
controller.imagePaths,
|
||||||
|
AppLocalizations.of(context),
|
||||||
);
|
);
|
||||||
return contextMenuActions
|
return contextMenuActions
|
||||||
.map((action) => _mailboxFocusedMenuItem(context, action, mailbox))
|
.map((action) => _mailboxFocusedMenuItem(context, action, mailbox))
|
||||||
@@ -231,30 +233,24 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
|
|||||||
isFocusedMenu: true
|
isFocusedMenu: true
|
||||||
),
|
),
|
||||||
title: Expanded(
|
title: Expanded(
|
||||||
child: AbsorbPointer(
|
child: Row(children: [
|
||||||
absorbing: !contextMenuItem.isActivated,
|
SvgPicture.asset(
|
||||||
child: Opacity(
|
contextMenuItem.action.getContextMenuIcon(controller.imagePaths),
|
||||||
opacity: contextMenuItem.isActivated ? 1.0 : 0.3,
|
width: 24,
|
||||||
child: Row(children: [
|
height: 24,
|
||||||
SvgPicture.asset(
|
fit: BoxFit.fill,
|
||||||
contextMenuItem.action.getContextMenuIcon(controller.imagePaths),
|
colorFilter: contextMenuItem.action.getPopupMenuIconColor().asFilter()
|
||||||
width: 24,
|
|
||||||
height: 24,
|
|
||||||
fit: BoxFit.fill,
|
|
||||||
colorFilter: contextMenuItem.action.getColorContextMenuIcon().asFilter()
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Expanded(child: Text(
|
|
||||||
contextMenuItem.action.getTitleContextMenu(context),
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
fontSize: 16,
|
|
||||||
color: contextMenuItem.action.getColorContextMenuTitle()
|
|
||||||
)
|
|
||||||
)),
|
|
||||||
]),
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 12),
|
||||||
|
Expanded(child: Text(
|
||||||
|
contextMenuItem.action.getTitleContextMenu(AppLocalizations.of(context)),
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 16,
|
||||||
|
color: contextMenuItem.action.getPopupMenuTitleColor()
|
||||||
|
)
|
||||||
|
)),
|
||||||
|
]),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -278,6 +274,8 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
|
|||||||
controller.dashboardController.enableSpamReport,
|
controller.dashboardController.enableSpamReport,
|
||||||
deletedMessageVaultSupported,
|
deletedMessageVaultSupported,
|
||||||
isSubAddressingSupported,
|
isSubAddressingSupported,
|
||||||
|
controller.imagePaths,
|
||||||
|
AppLocalizations.of(context),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (contextMenuActions.isEmpty) {
|
if (contextMenuActions.isEmpty) {
|
||||||
@@ -287,13 +285,13 @@ class SearchMailboxView extends GetWidget<SearchMailboxController>
|
|||||||
if (controller.responsiveUtils.isScreenWithShortestSide(context) || position == null) {
|
if (controller.responsiveUtils.isScreenWithShortestSide(context) || position == null) {
|
||||||
controller.openContextMenuAction(
|
controller.openContextMenuAction(
|
||||||
context,
|
context,
|
||||||
contextMenuMailboxActionTiles(
|
[],
|
||||||
|
itemActions: contextMenuActions,
|
||||||
|
onContextMenuActionClick: (menuAction) => controller.handleMailboxAction(
|
||||||
context,
|
context,
|
||||||
controller.imagePaths,
|
menuAction.action,
|
||||||
mailbox,
|
mailbox,
|
||||||
contextMenuActions,
|
),
|
||||||
handleMailboxAction: controller.handleMailboxAction
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
controller.openPopupMenuAction(
|
controller.openPopupMenuAction(
|
||||||
|
|||||||
Reference in New Issue
Block a user