TF-4233 Handle edit label on mobile

This commit is contained in:
dab246
2026-01-05 17:00:28 +07:00
committed by Dat H. Pham
parent bac101021e
commit ac33424c30
8 changed files with 131 additions and 8 deletions
@@ -2,7 +2,9 @@ import 'package:core/presentation/resources/image_paths.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:labels/model/label.dart'; import 'package:labels/model/label.dart';
import 'package:tmail_ui_user/features/base/mixin/popup_context_menu_action_mixin.dart'; import 'package:tmail_ui_user/features/base/mixin/popup_context_menu_action_mixin.dart';
import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_item_action.dart';
import 'package:tmail_ui_user/features/base/widget/popup_menu/popup_menu_item_action_widget.dart'; import 'package:tmail_ui_user/features/base/widget/popup_menu/popup_menu_item_action_widget.dart';
import 'package:tmail_ui_user/features/labels/presentation/models/context_item_label_action.dart';
import 'package:tmail_ui_user/features/labels/presentation/models/label_action_type.dart'; import 'package:tmail_ui_user/features/labels/presentation/models/label_action_type.dart';
import 'package:tmail_ui_user/features/labels/presentation/models/popup_menu_item_label_action.dart'; import 'package:tmail_ui_user/features/labels/presentation/models/popup_menu_item_label_action.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/utils/labels/label_method_action_define.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/utils/labels/label_method_action_define.dart';
@@ -10,7 +12,7 @@ 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';
mixin LabelContextMenuMixin on PopupContextMenuActionMixin { mixin LabelContextMenuMixin on PopupContextMenuActionMixin {
Future<void> openLabelContextMenuAction( Future<void> _openLabelPopupMenuAction(
BuildContext context, BuildContext context,
ImagePaths imagePaths, ImagePaths imagePaths,
Label label, Label label,
@@ -68,4 +70,67 @@ mixin LabelContextMenuMixin on PopupContextMenuActionMixin {
popBack(); popBack();
onLabelActionTypeCallback(label, actionType); onLabelActionTypeCallback(label, actionType);
} }
ContextMenuItemAction _buildLabelContextMenuItem(
LabelActionType actionType,
AppLocalizations appLocalizations,
ImagePaths imagePaths,
) {
return ContextMenuItemLabelAction(
actionType,
appLocalizations,
imagePaths,
);
}
Future<void> _openLabelContextMenuAction(
BuildContext context,
ImagePaths imagePaths,
Label label,
OnLabelActionTypeCallback onLabelActionTypeCallback,
) async {
final listLabelAction = [LabelActionType.edit];
final contextMenuActions = listLabelAction
.map((actionType) => _buildLabelContextMenuItem(
actionType,
AppLocalizations.of(context),
imagePaths,
))
.toList();
return openBottomSheetContextMenuAction(
context: context,
itemActions: contextMenuActions,
onContextMenuActionClick: (menuAction) {
popBack();
onLabelActionTypeCallback(label, menuAction.action);
},
);
}
Future<void> openLabelMenuAction(
BuildContext context,
ImagePaths imagePaths,
Label label,
OnLabelActionTypeCallback onLabelActionTypeCallback,
{RelativeRect? position}
) async {
if (position == null) {
return _openLabelContextMenuAction(
context,
imagePaths,
label,
onLabelActionTypeCallback,
);
} else {
return _openLabelPopupMenuAction(
context,
imagePaths,
label,
position,
onLabelActionTypeCallback,
);
}
}
} }
@@ -0,0 +1,29 @@
import 'package:core/presentation/resources/image_paths.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/labels/presentation/models/label_action_type.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class ContextMenuItemLabelAction
extends ContextMenuItemActionRequiredIcon<LabelActionType> {
final AppLocalizations appLocalizations;
final ImagePaths imagePaths;
ContextMenuItemLabelAction(
super.action,
this.appLocalizations,
this.imagePaths,
);
@override
String get actionIcon => action.getContextMenuIcon(imagePaths);
@override
String get actionName => action.getContextMenuTitle(appLocalizations);
@override
Color get actionIconColor => action.getContextMenuIconColor();
@override
Color get actionNameColor => action.getContextMenuTitleColor();
}
@@ -75,7 +75,6 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
if (selectedLabel != null) { if (selectedLabel != null) {
_nameInputController.text = selectedLabel.safeDisplayName; _nameInputController.text = selectedLabel.safeDisplayName;
_nameInputFocusNode.requestFocus(); _nameInputFocusNode.requestFocus();
_labelSelectedColorNotifier.value = _selectedColor;
_createLabelStateNotifier.value = true; _createLabelStateNotifier.value = true;
} }
}); });
@@ -426,12 +426,18 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
PresentationLabelMailbox.initial(label), PresentationLabelMailbox.initial(label),
), ),
onOpenContextMenu: (label, position) => onOpenContextMenu: (label, position) =>
dashboardController.openLabelContextMenuAction( dashboardController.openLabelPopupMenuAction(
context, context,
controller.imagePaths, controller.imagePaths,
label, label,
position, position,
), ),
onLongPressLabelItemAction: (label) =>
dashboardController.openLabelContextMenuAction(
context,
controller.imagePaths,
label,
),
) )
: const Offstage(), : const Offstage(),
); );
@@ -7,7 +7,7 @@ import 'package:tmail_ui_user/features/labels/presentation/models/label_action_t
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
extension HandleLabelActionTypeExtension on MailboxDashBoardController { extension HandleLabelActionTypeExtension on MailboxDashBoardController {
Future<void> openLabelContextMenuAction( Future<void> openLabelPopupMenuAction(
BuildContext context, BuildContext context,
ImagePaths imagePaths, ImagePaths imagePaths,
Label label, Label label,
@@ -17,11 +17,11 @@ extension HandleLabelActionTypeExtension on MailboxDashBoardController {
isPopupMenuOpened.value = true; isPopupMenuOpened.value = true;
} }
return labelController return labelController
.openLabelContextMenuAction( .openLabelMenuAction(
context, context,
imagePaths, imagePaths,
label, label,
position, position: position,
_onPerformLabelActionType, _onPerformLabelActionType,
) )
.whenComplete(() { .whenComplete(() {
@@ -38,4 +38,17 @@ extension HandleLabelActionTypeExtension on MailboxDashBoardController {
label: label, label: label,
); );
} }
Future<void> openLabelContextMenuAction(
BuildContext context,
ImagePaths imagePaths,
Label label,
) async {
return labelController.openLabelMenuAction(
context,
imagePaths,
label,
_onPerformLabelActionType,
);
}
} }
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:labels/labels.dart'; import 'package:labels/labels.dart';
import 'package:tmail_ui_user/features/labels/presentation/models/label_action_type.dart'; import 'package:tmail_ui_user/features/labels/presentation/models/label_action_type.dart';
typedef OnOpenLabelCallback = void Function(Label label);
typedef OnOpenLabelContextMenuAction = Future<void> Function( typedef OnOpenLabelContextMenuAction = Future<void> Function(
Label label, Label label,
RelativeRect position, RelativeRect position,
@@ -11,3 +13,5 @@ typedef OnLabelActionTypeCallback = void Function(
Label label, Label label,
LabelActionType actionType, LabelActionType actionType,
); );
typedef OnLongPressLabelItemAction = void Function(Label label);
@@ -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/views/button/tmail_button_widget.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:labels/extensions/label_extension.dart'; import 'package:labels/extensions/label_extension.dart';
import 'package:labels/model/label.dart'; import 'package:labels/model/label.dart';
@@ -10,8 +11,6 @@ import 'package:tmail_ui_user/features/mailbox/presentation/utils/labels/label_m
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_icon_widget.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_icon_widget.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_name_widget.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/labels/label_name_widget.dart';
typedef OnOpenLabelCallback = void Function(Label label);
class LabelListItem extends StatefulWidget { class LabelListItem extends StatefulWidget {
final Label label; final Label label;
final ImagePaths imagePaths; final ImagePaths imagePaths;
@@ -20,6 +19,7 @@ class LabelListItem extends StatefulWidget {
final bool isMobileResponsive; final bool isMobileResponsive;
final OnOpenLabelCallback onOpenLabelCallback; final OnOpenLabelCallback onOpenLabelCallback;
final OnOpenLabelContextMenuAction? onOpenContextMenu; final OnOpenLabelContextMenuAction? onOpenContextMenu;
final OnLongPressLabelItemAction? onLongPressLabelItemAction;
const LabelListItem({ const LabelListItem({
super.key, super.key,
@@ -30,6 +30,7 @@ class LabelListItem extends StatefulWidget {
this.isSelected = false, this.isSelected = false,
this.isMobileResponsive = false, this.isMobileResponsive = false,
this.onOpenContextMenu, this.onOpenContextMenu,
this.onLongPressLabelItemAction,
}); });
@override @override
@@ -84,6 +85,9 @@ class _LabelListItemState extends State<LabelListItem> {
borderRadius: _borderRadius, borderRadius: _borderRadius,
onHover: _handleHoverChanged, onHover: _handleHoverChanged,
onTap: () => widget.onOpenLabelCallback(widget.label), onTap: () => widget.onOpenLabelCallback(widget.label),
onLongPress: PlatformInfo.isWebTouchDevice || PlatformInfo.isMobile
? () => widget.onLongPressLabelItemAction?.call(widget.label)
: null,
child: Container( child: Container(
height: _itemHeight, height: _itemHeight,
padding: _itemPadding, padding: _itemPadding,
@@ -13,6 +13,7 @@ class LabelListView extends StatelessWidget {
final OnOpenLabelCallback onOpenLabelCallback; final OnOpenLabelCallback onOpenLabelCallback;
final bool isMobileResponsive; final bool isMobileResponsive;
final OnOpenLabelContextMenuAction? onOpenContextMenu; final OnOpenLabelContextMenuAction? onOpenContextMenu;
final OnLongPressLabelItemAction? onLongPressLabelItemAction;
const LabelListView({ const LabelListView({
super.key, super.key,
@@ -23,6 +24,7 @@ class LabelListView extends StatelessWidget {
this.labelIdSelected, this.labelIdSelected,
this.isMobileResponsive = false, this.isMobileResponsive = false,
this.onOpenContextMenu, this.onOpenContextMenu,
this.onLongPressLabelItemAction,
}); });
@override @override
@@ -43,6 +45,7 @@ class LabelListView extends StatelessWidget {
onOpenLabelCallback: onOpenLabelCallback, onOpenLabelCallback: onOpenLabelCallback,
isMobileResponsive: isMobileResponsive, isMobileResponsive: isMobileResponsive,
onOpenContextMenu: onOpenContextMenu, onOpenContextMenu: onOpenContextMenu,
onLongPressLabelItemAction: onLongPressLabelItemAction,
); );
}, },
); );