TF-3766 Change context menu style for other widgets on mobile
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -11,51 +11,49 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||
|
||||
mixin PopupContextMenuActionMixin {
|
||||
|
||||
void openContextMenuAction(
|
||||
Future<void> openContextMenuAction(
|
||||
BuildContext context,
|
||||
List<Widget> actionTiles,
|
||||
{
|
||||
Widget? cancelButton,
|
||||
Key? key,
|
||||
List<ContextMenuItemAction>? itemActions,
|
||||
OnContextMenuActionClick? onContextMenuActionClick,
|
||||
}
|
||||
) async {
|
||||
if (actionTiles.isNotEmpty) {
|
||||
await (CupertinoActionSheetBuilder(context, key: key)
|
||||
..addTiles(actionTiles)
|
||||
..addCancelButton(cancelButton ?? buildCancelButton(context)))
|
||||
.show();
|
||||
} else {
|
||||
await showModalBottomSheet(
|
||||
context: context,
|
||||
showDragHandle: true,
|
||||
useSafeArea: true,
|
||||
isScrollControlled: true,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(16.0),
|
||||
topRight: Radius.circular(16.0),
|
||||
),
|
||||
await (CupertinoActionSheetBuilder(context)
|
||||
..addTiles(actionTiles)
|
||||
..addCancelButton(buildCancelButton(context)))
|
||||
.show();
|
||||
}
|
||||
|
||||
Future<void> openBottomSheetContextMenuAction({
|
||||
required BuildContext context,
|
||||
required List<ContextMenuItemAction> itemActions,
|
||||
required OnContextMenuActionClick onContextMenuActionClick,
|
||||
Key? key,
|
||||
}) async {
|
||||
await showModalBottomSheet(
|
||||
context: context,
|
||||
showDragHandle: true,
|
||||
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 PointerInterceptor(
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsetsDirectional.only(bottom: 24),
|
||||
child: ContextMenuDialogView(
|
||||
actions: itemActions ?? [],
|
||||
onContextMenuActionClick: (menuAction) =>
|
||||
onContextMenuActionClick?.call(menuAction),
|
||||
),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
barrierColor: Colors.black.withOpacity(0.2),
|
||||
builder: (_) {
|
||||
return PointerInterceptor(
|
||||
child: Container(
|
||||
key: key,
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsetsDirectional.only(bottom: 24),
|
||||
child: ContextMenuDialogView(
|
||||
actions: itemActions,
|
||||
onContextMenuActionClick: onContextMenuActionClick,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void openPopupMenuAction(
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -17,6 +16,76 @@ class ContextMenuDialogItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SvgPicture? icon;
|
||||
SvgPicture? selectedIcon;
|
||||
bool isSelected = false;
|
||||
|
||||
if (menuAction is ContextMenuItemActionRequiredIcon) {
|
||||
final specificMenuAction =
|
||||
menuAction as ContextMenuItemActionRequiredIcon;
|
||||
icon = SvgPicture.asset(
|
||||
specificMenuAction.actionIcon,
|
||||
width: 20,
|
||||
height: 20,
|
||||
colorFilter: specificMenuAction.actionIconColor.asFilter(),
|
||||
fit: BoxFit.fill,
|
||||
);
|
||||
} else if (menuAction is ContextMenuItemActionRequiredSelectedIcon) {
|
||||
final specificMenuAction =
|
||||
menuAction as ContextMenuItemActionRequiredSelectedIcon;
|
||||
selectedIcon = SvgPicture.asset(
|
||||
specificMenuAction.selectedIcon,
|
||||
width: 20,
|
||||
height: 20,
|
||||
colorFilter: specificMenuAction.selectedIconColor.asFilter(),
|
||||
fit: BoxFit.fill,
|
||||
);
|
||||
isSelected = specificMenuAction.selectedAction == menuAction.action;
|
||||
} else if (menuAction is ContextMenuItemActionRequiredFull) {
|
||||
final specificMenuAction =
|
||||
menuAction as ContextMenuItemActionRequiredFull;
|
||||
|
||||
icon = SvgPicture.asset(
|
||||
specificMenuAction.actionIcon,
|
||||
width: 20,
|
||||
height: 20,
|
||||
colorFilter: specificMenuAction.actionIconColor.asFilter(),
|
||||
fit: BoxFit.fill,
|
||||
);
|
||||
selectedIcon = SvgPicture.asset(
|
||||
specificMenuAction.selectedIcon,
|
||||
width: 20,
|
||||
height: 20,
|
||||
colorFilter: specificMenuAction.selectedIconColor.asFilter(),
|
||||
fit: BoxFit.fill,
|
||||
);
|
||||
isSelected = specificMenuAction.selectedAction == menuAction.action;
|
||||
}
|
||||
|
||||
Widget? iconWidget = icon != null
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Container(
|
||||
height: 32,
|
||||
width: 32,
|
||||
alignment: Alignment.center,
|
||||
child: icon,
|
||||
),
|
||||
)
|
||||
: null;
|
||||
|
||||
Widget? selectedIconWidget = selectedIcon != null
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Container(
|
||||
height: 32,
|
||||
width: 32,
|
||||
alignment: Alignment.center,
|
||||
child: selectedIcon,
|
||||
),
|
||||
)
|
||||
: null;
|
||||
|
||||
return Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
@@ -25,31 +94,24 @@ class ContextMenuDialogItem extends StatelessWidget {
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (iconWidget != null) iconWidget else const SizedBox(width: 24),
|
||||
Expanded(
|
||||
child: Text(
|
||||
menuAction.actionName,
|
||||
style: ThemeUtils.textStyleInter400.copyWith(
|
||||
color: menuAction.actionNameColor,
|
||||
letterSpacing: -0.15,
|
||||
fontSize: 16,
|
||||
height: 21.01 / 16,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
if (isSelected && selectedIconWidget != null)
|
||||
selectedIconWidget
|
||||
else
|
||||
const SizedBox(width: 24),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -12,13 +12,41 @@ abstract class ContextMenuItemAction<T> with EquatableMixin {
|
||||
@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);
|
||||
}
|
||||
|
||||
mixin OptionalIcon {
|
||||
String get actionIcon;
|
||||
|
||||
Color get actionIconColor => AppColor.gray424244.withOpacity(0.72);
|
||||
}
|
||||
|
||||
mixin OptionalSelectedIcon<T> {
|
||||
String get selectedIcon;
|
||||
|
||||
Color get selectedIconColor => AppColor.primaryMain;
|
||||
}
|
||||
|
||||
abstract class ContextMenuItemActionRequiredIcon<T>
|
||||
extends ContextMenuItemAction<T> with OptionalIcon {
|
||||
ContextMenuItemActionRequiredIcon(super.action);
|
||||
}
|
||||
|
||||
abstract class ContextMenuItemActionRequiredSelectedIcon<T>
|
||||
extends ContextMenuItemAction<T> with OptionalSelectedIcon<T> {
|
||||
|
||||
final T? selectedAction;
|
||||
|
||||
ContextMenuItemActionRequiredSelectedIcon(super.action, this.selectedAction);
|
||||
}
|
||||
|
||||
abstract class ContextMenuItemActionRequiredFull<T>
|
||||
extends ContextMenuItemAction<T> with OptionalIcon, OptionalSelectedIcon<T> {
|
||||
final T selectedAction;
|
||||
|
||||
ContextMenuItemActionRequiredFull(super.action, this.selectedAction);
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import 'package:rule_filter/rule_filter/rule_condition_group.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/font_name_type.dart';
|
||||
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/extensions/rule_condition_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
|
||||
@@ -173,6 +174,8 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
}
|
||||
|
||||
String _getTextItemDropdown(BuildContext context, {required T? item}) {
|
||||
final appLocalizations = AppLocalizations.of(context);
|
||||
|
||||
if (item is Identity) {
|
||||
return item.name ?? '';
|
||||
}
|
||||
@@ -183,16 +186,16 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
||||
return item.name;
|
||||
}
|
||||
if (item is rule_condition.Field) {
|
||||
return item.getTitle(context);
|
||||
return item.getTitle(appLocalizations);
|
||||
}
|
||||
if (item is rule_condition.Comparator) {
|
||||
return item.getTitle(context);
|
||||
return item.getTitle(appLocalizations);
|
||||
}
|
||||
if (item is EmailRuleFilterAction) {
|
||||
return item.getTitle(context);
|
||||
return item.getTitle(appLocalizations);
|
||||
}
|
||||
if (item is ConditionCombiner) {
|
||||
return item.getTitle(context);
|
||||
return item.getTitle(appLocalizations);
|
||||
}
|
||||
return hintText ?? '';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user