TF-3766 Change context menu style for other widgets on mobile

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-06-13 01:14:16 +07:00
committed by Dat H. Pham
parent 3dce663b98
commit 2d175633e7
36 changed files with 759 additions and 612 deletions
@@ -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 ?? '';
}