TF-4004 Add Preview/Hide condition, action of rule filter

This commit is contained in:
dab246
2025-09-09 04:15:31 +07:00
committed by Dat H. Pham
parent a0123c41b0
commit 5983fb66ff
22 changed files with 685 additions and 393 deletions
@@ -243,6 +243,7 @@ extension AppColor on Color {
static const m3Neutral70 = Color(0xFFAEAAAE); static const m3Neutral70 = Color(0xFFAEAAAE);
static const m3Neutral90 = Color(0xFFE6E1E5); static const m3Neutral90 = Color(0xFFE6E1E5);
static const m3SysLightSecondaryBlue = Color(0xFF5C9CE6); static const m3SysLightSecondaryBlue = Color(0xFF5C9CE6);
static const m3SysLight = Color(0xFF0157AD);
static const grayBackgroundColor = Color(0xFFF3F6F9); static const grayBackgroundColor = Color(0xFFF3F6F9);
static const m3SurfaceBackground = Color(0xFF1C1B1F); static const m3SurfaceBackground = Color(0xFF1C1B1F);
static const warningColor = Color(0xFFFFC107); static const warningColor = Color(0xFFFFC107);
@@ -273,6 +274,11 @@ extension AppColor on Color {
static const gray49454F = Color(0xFF49454F); static const gray49454F = Color(0xFF49454F);
static const lightGrayF9FAFB = Color(0xFFF9FAFB); static const lightGrayF9FAFB = Color(0xFFF9FAFB);
static const black4D4D4D = Color(0xFF4D4D4D); static const black4D4D4D = Color(0xFF4D4D4D);
static const green166534 = Color(0xFF166534);
static const lightGreenF0FDF4 = Color(0xFFF0FDF4);
static const lightGreenBBF7D0 = Color(0xFFBBF7D0);
static const lightBlueEFF6FF = Color(0xFFEFF6FF);
static const lightBlueBFDBFE = Color(0xFFBFDBFE);
static const mapGradientColor = [ static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)], [Color(0xFF21D4FD), Color(0xFFB721FF)],
@@ -10,37 +10,33 @@ import 'package:tmail_ui_user/main/routes/route_utils.dart';
extension PresentationMailboxExtension on PresentationMailbox { extension PresentationMailboxExtension on PresentationMailbox {
String getDisplayNameByLocalizations(AppLocalizations appLocalizations) { String getDisplayName(BuildContext context) {
if (isDefault) { if (isDefault) {
switch(role!.value.toLowerCase()) { switch(role!.value.toLowerCase()) {
case PresentationMailbox.inboxRole: case PresentationMailbox.inboxRole:
return appLocalizations.inboxMailboxDisplayName; return AppLocalizations.of(context).inboxMailboxDisplayName;
case PresentationMailbox.archiveRole: case PresentationMailbox.archiveRole:
return appLocalizations.archiveMailboxDisplayName; return AppLocalizations.of(context).archiveMailboxDisplayName;
case PresentationMailbox.draftsRole: case PresentationMailbox.draftsRole:
return appLocalizations.draftsMailboxDisplayName; return AppLocalizations.of(context).draftsMailboxDisplayName;
case PresentationMailbox.sentRole: case PresentationMailbox.sentRole:
return appLocalizations.sentMailboxDisplayName; return AppLocalizations.of(context).sentMailboxDisplayName;
case PresentationMailbox.outboxRole: case PresentationMailbox.outboxRole:
return appLocalizations.outboxMailboxDisplayName; return AppLocalizations.of(context).outboxMailboxDisplayName;
case PresentationMailbox.trashRole: case PresentationMailbox.trashRole:
return appLocalizations.trashMailboxDisplayName; return AppLocalizations.of(context).trashMailboxDisplayName;
case PresentationMailbox.spamRole: case PresentationMailbox.spamRole:
case PresentationMailbox.junkRole: case PresentationMailbox.junkRole:
return appLocalizations.spamMailboxDisplayName; return AppLocalizations.of(context).spamMailboxDisplayName;
case PresentationMailbox.templatesRole: case PresentationMailbox.templatesRole:
return appLocalizations.templatesMailboxDisplayName; return AppLocalizations.of(context).templatesMailboxDisplayName;
case PresentationMailbox.recoveredRole: case PresentationMailbox.recoveredRole:
return appLocalizations.recoveredMailboxDisplayName; return AppLocalizations.of(context).recoveredMailboxDisplayName;
} }
} }
return name?.name ?? ''; return name?.name ?? '';
} }
String getDisplayName(BuildContext context) {
return getDisplayNameByLocalizations(AppLocalizations.of(context));
}
String getMailboxIcon(ImagePaths imagePaths) { String getMailboxIcon(ImagePaths imagePaths) {
if (hasRole()) { if (hasRole()) {
switch(role!.value) { switch(role!.value) {
@@ -39,11 +39,11 @@ extension ValicatorFailureExtension on VerifyNameFailure {
} }
} }
String getMessageRulesFilter(BuildContext context) { String getMessageRulesFilter(AppLocalizations appLocalizations) {
if (exception is EmptyNameException) { if (exception is EmptyNameException) {
return AppLocalizations.of(context).this_field_cannot_be_blank; return appLocalizations.this_field_cannot_be_blank;
} else if (exception is NameWithSpaceOnlyException) { } else if (exception is NameWithSpaceOnlyException) {
return AppLocalizations.of(context).thisFieldCannotContainOnlySpaces; return appLocalizations.thisFieldCannotContainOnlySpaces;
} else { } else {
return ''; return '';
} }
@@ -17,4 +17,14 @@ extension RuleConditionExtension on RuleCondition {
String getPreview(AppLocalizations appLocalizations) { String getPreview(AppLocalizations appLocalizations) {
return '${field.getTitle(appLocalizations)}, ${comparator.getTitle(appLocalizations).toLowerCase()}: $value'; return '${field.getTitle(appLocalizations)}, ${comparator.getTitle(appLocalizations).toLowerCase()}: $value';
} }
String getPreviewWhenEditing(AppLocalizations appLocalizations) {
return '${field.getTitle(appLocalizations)} ${comparator.getTitle(appLocalizations).toLowerCase()} "$value"';
}
}
extension ListRuleConditionExtension on List<RuleCondition> {
String getPreviewWhenEditing(AppLocalizations appLocalizations) {
return map((e) => e.getPreviewWhenEditing(appLocalizations)).join(', ');
}
} }
@@ -0,0 +1,38 @@
import 'package:core/presentation/extensions/capitalize_extension.dart';
import 'package:flutter/material.dart';
import 'package:rule_filter/rule_filter/rule_condition_group.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/tmail_rule_extension.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/extensions/list_rule_filter_action_argument_extension.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/rules_filter_creator_controller.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
extension HandleTogglePreviewRuleFilterExtension
on RulesFilterCreatorController {
void handleTogglePreviewRuleFilter() {
isPreviewEnabled.value = !isPreviewEnabled.value;
}
String getConditionPreview(AppLocalizations appLocalizations) {
final conditionCombiner =
(conditionCombinerType.value ?? ConditionCombiner.AND)
.getTitle(appLocalizations)
.toUpperCase();
final conditionValue = listRuleCondition.getPreviewWhenEditing(
appLocalizations,
);
return appLocalizations.ruleFilterConditionPreviewMessage(
conditionCombiner,
conditionValue,
);
}
String getActionPreview(BuildContext context) {
final actionValue = listEmailRuleFilterActionSelected.getPreviewWhenEditing(
context,
);
return '${AppLocalizations.of(context).actions.inCaps}: $actionValue';
}
}
@@ -1,7 +1,21 @@
import 'package:flutter/cupertino.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_action_arguments.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_action_arguments.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
extension ListRuleFilterActionArgumentExtension on List<RuleFilterActionArguments> { extension ListRuleFilterActionArgumentExtension on List<RuleFilterActionArguments> {
bool isEmptySelectedRuleAction() => every((argument) => argument is EmptyRuleFilterActionArguments); bool isEmptySelectedRuleAction() => every((argument) => argument is EmptyRuleFilterActionArguments);
String getPreviewWhenEditing(BuildContext context) {
final appLocalizations = AppLocalizations.of(context);
return where((arguments) => arguments.action != null).map((arguments) {
if (arguments is MoveMessageActionArguments) {
return '${arguments.action!.getTitle(appLocalizations)} ${appLocalizations.toFolder.toLowerCase()} "${arguments.mailbox?.getDisplayName(context) ?? ''}"';
} else {
return arguments.action!.getTitle(appLocalizations);
}
}).join(', ');
}
} }
@@ -26,4 +26,6 @@ enum EmailRuleFilterAction {
} }
bool get isSupported => this != EmailRuleFilterAction.forwardTo; bool get isSupported => this != EmailRuleFilterAction.forwardTo;
bool get isForwardTo => this == EmailRuleFilterAction.forwardTo;
} }
@@ -1,4 +0,0 @@
enum RuleFilterConditionScreenType {
mobile,
desktop
}
@@ -56,6 +56,7 @@ class RulesFilterCreatorController extends BaseMailboxController {
final mailboxSelected = Rxn<PresentationMailbox>(); final mailboxSelected = Rxn<PresentationMailbox>();
final actionType = CreatorActionType.create.obs; final actionType = CreatorActionType.create.obs;
final listRuleCondition = RxList<RuleCondition>(); final listRuleCondition = RxList<RuleCondition>();
final isPreviewEnabled = RxBool(false);
final TextEditingController inputRuleNameController = TextEditingController(); final TextEditingController inputRuleNameController = TextEditingController();
final FocusNode inputRuleNameFocusNode = FocusNode(); final FocusNode inputRuleNameFocusNode = FocusNode();
@@ -124,17 +125,17 @@ class RulesFilterCreatorController extends BaseMailboxController {
@override @override
void handleSuccessViewState(Success success) async { void handleSuccessViewState(Success success) async {
super.handleSuccessViewState(success);
if (success is GetAllMailboxSuccess) { if (success is GetAllMailboxSuccess) {
await buildTree(success.mailboxList); await buildTree(success.mailboxList);
if (currentContext != null) { if (currentContext != null) {
syncAllMailboxWithDisplayName(currentContext!); syncAllMailboxWithDisplayName(currentContext!);
} }
} else if (success is GetAllRulesSuccess) { } else if (success is GetAllRulesSuccess) {
log('RulesFilterCreatorController::handleSuccessViewState():GetAllRulesSuccess: ${success.rules}');
if (success.rules?.isNotEmpty == true) { if (success.rules?.isNotEmpty == true) {
_listEmailRule = success.rules!; _listEmailRule = success.rules!;
} }
} else {
super.handleSuccessViewState(success);
} }
} }
@@ -283,21 +284,31 @@ class RulesFilterCreatorController extends BaseMailboxController {
} }
} }
void updateRuleName(BuildContext context, String? value) { void updateRuleName(AppLocalizations appLocalizations, String? value) {
_newRuleName = value; _newRuleName = value;
errorRuleName.value = _getErrorStringByInputValue(context, _newRuleName); errorRuleName.value = _getErrorStringByInputValue(
appLocalizations,
_newRuleName,
);
} }
void updateConditionValue(BuildContext context, String? value, int ruleConditionIndex) { void updateConditionValue(
RuleCondition newRuleCondition = RuleCondition( AppLocalizations appLocalizations,
String value,
int ruleConditionIndex,
) {
final newRuleCondition = RuleCondition(
field: listRuleCondition[ruleConditionIndex].field, field: listRuleCondition[ruleConditionIndex].field,
comparator: listRuleCondition[ruleConditionIndex].comparator, comparator: listRuleCondition[ruleConditionIndex].comparator,
value: value!, value: value,
); );
listRuleCondition[ruleConditionIndex] = newRuleCondition; listRuleCondition[ruleConditionIndex] = newRuleCondition;
listRuleCondition.refresh(); listRuleCondition.refresh();
String? errorString = _getErrorStringByInputValue(context, listRuleCondition[ruleConditionIndex].value); final errorString = _getErrorStringByInputValue(
RulesFilterInputFieldArguments newRuleConditionValueArguments = RulesFilterInputFieldArguments( appLocalizations,
listRuleCondition[ruleConditionIndex].value,
);
final newRuleConditionValueArguments = RulesFilterInputFieldArguments(
focusNode: listRuleConditionValueArguments[ruleConditionIndex].focusNode, focusNode: listRuleConditionValueArguments[ruleConditionIndex].focusNode,
errorText: errorString, errorText: errorString,
controller: listRuleConditionValueArguments[ruleConditionIndex].controller, controller: listRuleConditionValueArguments[ruleConditionIndex].controller,
@@ -310,7 +321,10 @@ class RulesFilterCreatorController extends BaseMailboxController {
listRuleConditionValueArguments.refresh(); listRuleConditionValueArguments.refresh();
} }
String? _getErrorStringByInputValue(BuildContext context, String? inputValue) { String? _getErrorStringByInputValue(
AppLocalizations appLocalizations,
String? inputValue,
) {
return verifyNameInteractor.execute( return verifyNameInteractor.execute(
inputValue, inputValue,
[ [
@@ -320,7 +334,7 @@ class RulesFilterCreatorController extends BaseMailboxController {
).fold( ).fold(
(failure) { (failure) {
if (failure is VerifyNameFailure) { if (failure is VerifyNameFailure) {
return failure.getMessageRulesFilter(context); return failure.getMessageRulesFilter(appLocalizations);
} else { } else {
return null; return null;
} }
@@ -416,7 +430,10 @@ class RulesFilterCreatorController extends BaseMailboxController {
} }
} }
void selectMailbox(BuildContext context, int ruleFilterActionIndex) async { Future<void> selectMailbox(
BuildContext context,
int ruleFilterActionIndex,
) async {
if (_accountId != null) { if (_accountId != null) {
final arguments = DestinationPickerArguments( final arguments = DestinationPickerArguments(
_accountId!, _accountId!,
@@ -430,8 +447,9 @@ class RulesFilterCreatorController extends BaseMailboxController {
if (destinationMailbox is PresentationMailbox && context.mounted) { if (destinationMailbox is PresentationMailbox && context.mounted) {
mailboxSelected.value = destinationMailbox; mailboxSelected.value = destinationMailbox;
errorMailboxSelectedValue.value = _getErrorStringByInputValue( errorMailboxSelectedValue.value = _getErrorStringByInputValue(
context, AppLocalizations.of(context),
mailboxSelected.value?.getDisplayName(context)); destinationMailbox.getDisplayName(context),
);
RuleFilterActionArguments newRuleFilterAction = MoveMessageActionArguments(mailbox: mailboxSelected.value); RuleFilterActionArguments newRuleFilterAction = MoveMessageActionArguments(mailbox: mailboxSelected.value);
listEmailRuleFilterActionSelected[ruleFilterActionIndex] = newRuleFilterAction; listEmailRuleFilterActionSelected[ruleFilterActionIndex] = newRuleFilterAction;
} }
@@ -439,29 +457,30 @@ class RulesFilterCreatorController extends BaseMailboxController {
} }
void createNewRuleFilter(BuildContext context) { void createNewRuleFilter(BuildContext context) {
KeyboardUtils.hideKeyboard(context); final appLocalizations = AppLocalizations.of(context);
final errorName = _getErrorStringByInputValue(
final errorName = _getErrorStringByInputValue(context, _newRuleName); appLocalizations,
log('RulesFilterCreatorController::createNewRuleFilter:errorName: $errorName'); _newRuleName,
);
if (errorName?.isNotEmpty == true) { if (errorName?.isNotEmpty == true) {
errorRuleName.value = errorName; errorRuleName.value = errorName;
inputRuleNameFocusNode.requestFocus(); inputRuleNameFocusNode.requestFocus();
return; return;
} }
if (listRuleCondition.isEmpty if (listRuleCondition.isEmpty) {
&& currentOverlayContext != null
&& currentContext != null
) {
appToast.showToastErrorMessage( appToast.showToastErrorMessage(
currentOverlayContext!, context,
AppLocalizations.of(currentContext!).youHaveNotAddedConditionToRule); appLocalizations.youHaveNotAddedConditionToRule,
);
return; return;
} }
for (var ruleCondition in listRuleCondition) { for (var ruleCondition in listRuleCondition) {
final errorConditionString = _getErrorStringByInputValue(context, ruleCondition.value); final errorConditionString = _getErrorStringByInputValue(
log('RulesFilterCreatorController::createNewRuleFilter:errorConditionString: $errorConditionString'); appLocalizations,
ruleCondition.value,
);
if (errorConditionString != null) { if (errorConditionString != null) {
int ruleConditionIndex = listRuleCondition.indexOf(ruleCondition); int ruleConditionIndex = listRuleCondition.indexOf(ruleCondition);
RulesFilterInputFieldArguments newRuleConditionValueArguments = RulesFilterInputFieldArguments( RulesFilterInputFieldArguments newRuleConditionValueArguments = RulesFilterInputFieldArguments(
@@ -475,50 +494,51 @@ class RulesFilterCreatorController extends BaseMailboxController {
} }
} }
if (listEmailRuleFilterActionSelected.isEmpty if (listEmailRuleFilterActionSelected.isEmpty) {
&& currentOverlayContext != null
&& currentContext != null
) {
appToast.showToastErrorMessage( appToast.showToastErrorMessage(
currentOverlayContext!, context,
AppLocalizations.of(currentContext!).youHaveNotAddedActionToRule); appLocalizations.youHaveNotAddedActionToRule,
);
return; return;
} }
if (listEmailRuleFilterActionSelected.isEmptySelectedRuleAction() if (listEmailRuleFilterActionSelected.isEmptySelectedRuleAction()) {
&& currentOverlayContext != null
&& currentContext != null
) {
appToast.showToastErrorMessage( appToast.showToastErrorMessage(
currentOverlayContext!, context,
AppLocalizations.of(currentContext!).youHaveNotSelectedAnyActionForRule); appLocalizations.youHaveNotSelectedAnyActionForRule,
);
return; return;
} }
for (var ruleFilterAction in listEmailRuleFilterActionSelected) { for (var ruleFilterAction in listEmailRuleFilterActionSelected) {
if (ruleFilterAction is MoveMessageActionArguments) { if (ruleFilterAction is MoveMessageActionArguments) {
final errorAction = _getErrorStringByInputValue(context, mailboxSelected.value?.getDisplayName(context)); final errorAction = _getErrorStringByInputValue(
log('RulesFilterCreatorController::createNewRuleFilter:errorAction: $errorAction'); appLocalizations,
mailboxSelected.value?.getDisplayName(context),
);
if (errorAction?.isNotEmpty == true) { if (errorAction?.isNotEmpty == true) {
appToast.showToastErrorMessage( appToast.showToastErrorMessage(
context, context,
AppLocalizations.of(context).notSelectedMailboxToMoveMessage); appLocalizations.notSelectedMailboxToMoveMessage,
);
return; return;
} }
} }
if (ruleFilterAction is MarkAsSpamActionArguments) { if (ruleFilterAction is MarkAsSpamActionArguments) {
final spamMailboxId = getSpamMailboxId(); final spamMailboxId = getSpamMailboxId();
log('RulesFilterCreatorController::createNewRuleFilter:spamMailboxId: ${spamMailboxId?.asString}');
if (spamMailboxId == null) { if (spamMailboxId == null) {
appToast.showToastErrorMessage( appToast.showToastErrorMessage(
context, context,
AppLocalizations.of(context).spamFolderNotFound); appLocalizations.spamFolderNotFound,
);
return; return;
} }
} }
if (ruleFilterAction is ForwardActionArguments) { if (ruleFilterAction is ForwardActionArguments) {
final errorAction = _getErrorStringByInputValue(context, ruleFilterAction.forwardEmail); final errorAction = _getErrorStringByInputValue(
log('RulesFilterCreatorController::createNewRuleFilter:errorAction: $errorAction'); appLocalizations,
ruleFilterAction.forwardEmail,
);
if (errorAction?.isNotEmpty == true) { if (errorAction?.isNotEmpty == true) {
errorForwardEmailValue.value = errorAction; errorForwardEmailValue.value = errorAction;
forwardEmailFocusNode.requestFocus(); forwardEmailFocusNode.requestFocus();
@@ -661,12 +681,17 @@ class RulesFilterCreatorController extends BaseMailboxController {
listEmailRuleFilterActionSelected.removeAt(ruleFilterActionIndex); listEmailRuleFilterActionSelected.removeAt(ruleFilterActionIndex);
} }
void updateForwardEmailValue(BuildContext context, String? value, int ruleActionIndex) { void updateForwardEmailValue(
String? errorAction = _getErrorStringByInputValue(context, value); AppLocalizations appLocalizations,
log('RulesFilterCreatorController::createNewRuleFilter:errorAction: $errorAction'); String? value,
RuleFilterActionArguments newRuleFilterAction = ForwardActionArguments(forwardEmail: value); int ruleActionIndex,
errorForwardEmailValue.value = errorAction; ) {
listEmailRuleFilterActionSelected[ruleActionIndex] = newRuleFilterAction; errorForwardEmailValue.value = _getErrorStringByInputValue(
appLocalizations,
value,
);
listEmailRuleFilterActionSelected[ruleActionIndex] =
ForwardActionArguments(forwardEmail: value);
listEmailRuleFilterActionSelected.refresh(); listEmailRuleFilterActionSelected.refresh();
} }
} }
@@ -6,14 +6,16 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_close_button_widget.dart'; import 'package:tmail_ui_user/features/base/widget/default_field/default_close_button_widget.dart';
import 'package:tmail_ui_user/features/base/widget/label_input_field_builder.dart'; import 'package:tmail_ui_user/features/base/widget/label_input_field_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/extensions/handle_toggle_preview_rule_filter_extension.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/extensions/select_rule_action_field_extension.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/extensions/select_rule_action_field_extension.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_action_arguments.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_action_arguments.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_controller.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_controller.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_widget.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_widget.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_list_action_widget.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_list_action_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_title_with_preview_button.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_title_builder.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_title_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_preview_banner.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> { class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
@@ -25,10 +27,8 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final responsiveUtil = controller.responsiveUtils; final responsiveUtils = controller.responsiveUtils;
final isMobile = responsiveUtil.isMobile(context); final isMobile = responsiveUtils.isMobile(context);
final currentScreenHeight = responsiveUtil.getSizeScreenHeight(context);
final currentScreenWidth = responsiveUtil.getSizeScreenWidth(context);
Widget bodyWidget = Container( Widget bodyWidget = Container(
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -49,23 +49,19 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
blurRadius: 2, blurRadius: 2,
), ),
], ],
), ),
width: isMobile width: _getViewWidth(
? double.infinity : isMobile,
math.min( responsiveUtils.getSizeScreenWidth(context),
currentScreenWidth, ),
612,
),
constraints: BoxConstraints( constraints: BoxConstraints(
maxHeight: isMobile maxHeight: _getViewMaxHeight(
? double.infinity isMobile,
: math.min( responsiveUtils.getSizeScreenHeight(context),
currentScreenHeight - 100, ),
674,
),
), ),
clipBehavior: isMobile ? Clip.none : Clip.antiAlias, clipBehavior: isMobile ? Clip.none : Clip.antiAlias,
child: _buildRulesFilterForm(context, isMobile), child: _buildRulesFilterForm(context, isMobile, responsiveUtils),
); );
if (isMobile) { if (isMobile) {
@@ -83,7 +79,11 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
return bodyWidget; return bodyWidget;
} }
Widget _buildRulesFilterForm(BuildContext context, bool isMobile) { Widget _buildRulesFilterForm(
BuildContext context,
bool isMobile,
ResponsiveUtils responsiveUtils,
) {
final appLocalizations = AppLocalizations.of(context); final appLocalizations = AppLocalizations.of(context);
Widget formWidget = Column( Widget formWidget = Column(
@@ -91,7 +91,7 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
children: [ children: [
if (!isMobile) if (!isMobile)
Container( Container(
padding: const EdgeInsets.only(top: 24, bottom: 12), padding: const EdgeInsets.only(top: 24, bottom: 16),
alignment: Alignment.center, alignment: Alignment.center,
child: Obx( child: Obx(
() => Text( () => Text(
@@ -106,7 +106,7 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
else else
Container( Container(
height: 64, height: 64,
padding: _getPadding(context), padding: const EdgeInsetsDirectional.only(start: 8, end: 16),
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
@@ -140,18 +140,15 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
child: SingleChildScrollView( child: SingleChildScrollView(
physics: const ClampingScrollPhysics(), physics: const ClampingScrollPhysics(),
child: Padding( child: Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(horizontal: isMobile ? 16 : 32),
horizontal: isMobile ? 16 : 32,
),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Obx( Obx(
() => LabelInputFieldBuilder( () => LabelInputFieldBuilder(
label: appLocalizations.ruleName, label: appLocalizations.ruleName,
hintText: appLocalizations.rulesNameHintTextInput, hintText: appLocalizations.rulesNameHintTextInput,
textEditingController: textEditingController: controller.inputRuleNameController,
controller.inputRuleNameController,
focusNode: controller.inputRuleNameFocusNode, focusNode: controller.inputRuleNameFocusNode,
errorText: controller.errorRuleName.value, errorText: controller.errorRuleName.value,
arrangeHorizontally: false, arrangeHorizontally: false,
@@ -163,41 +160,111 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
), ),
runSpacing: 16, runSpacing: 16,
inputFieldMaxWidth: double.infinity, inputFieldMaxWidth: double.infinity,
onTextChange: (value) => onTextChange: (value) => controller.updateRuleName(
controller.updateRuleName(context, value), appLocalizations,
), value,
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 24,
),
child: Text(
appLocalizations.condition,
style: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
), ),
), ),
), ),
if (!isMobile)
Obx(() => RuleFilterTitleWithPreviewButton(
imagePaths: controller.imagePaths,
isPreviewEnabled: controller.isPreviewEnabled.value,
onTogglePreviewAction:
controller.handleTogglePreviewRuleFilter,
))
else
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Text(
appLocalizations.condition,
style: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
),
if (!isMobile)
Obx(() {
if (controller.isPreviewEnabled.isTrue) {
return RulePreviewBanner(
imagePaths: controller.imagePaths,
message: controller.getConditionPreview(
appLocalizations,
),
isAction: false,
margin: const EdgeInsetsDirectional.only(bottom: 16),
);
} else {
return const SizedBox.shrink();
}
}),
Obx( Obx(
() => RuleFilterTitle( () => RuleFilterTitle(
conditionCombinerType: controller.conditionCombinerType.value, conditionCombinerType: controller
.conditionCombinerType
.value,
imagePaths: controller.imagePaths, imagePaths: controller.imagePaths,
isMobile: isMobile, isMobile: isMobile,
onTapActionCallback: (value) => onTapActionCallback: (value) =>
controller.selectConditionCombiner( controller.selectConditionCombiner(
context: context, context: context,
combinerType: value, combinerType: value,
isMobile: isMobile, isMobile: isMobile,
), ),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
_buildListRuleFilterConditionList( Obx(() {
context: context, return ListView.builder(
isMobile: isMobile, shrinkWrap: true,
), primary: false,
itemCount: controller.listRuleCondition.length,
itemBuilder: (context, index) {
final conditionItem = controller
.listRuleConditionValueArguments[index];
return RuleFilterConditionWidget(
key: ValueKey(conditionItem.focusNode),
isMobile: isMobile,
ruleCondition: controller.listRuleCondition[index],
imagePaths: controller.imagePaths,
conditionValueErrorText: conditionItem.errorText,
conditionValueFocusNode: conditionItem.focusNode,
textEditingController: conditionItem.controller,
tapRuleConditionFieldCallback: (value) {
controller.selectRuleConditionFieldAction(
context,
value,
controller.listRuleCondition[index].field,
isMobile,
index,
);
},
tapRuleConditionComparatorCallback: (value) {
controller.selectRuleConditionComparatorAction(
context,
value,
controller.listRuleCondition[index].comparator,
isMobile,
index,
);
},
conditionValueOnChangeAction: (value) {
controller.updateConditionValue(
appLocalizations,
value,
index,
);
},
onDeleteRuleConditionAction: () {
controller.tapRemoveCondition(index);
},
);
},
);
}),
Container( Container(
constraints: const BoxConstraints(minWidth: 161), constraints: const BoxConstraints(minWidth: 161),
height: 36, height: 36,
@@ -225,7 +292,88 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
), ),
), ),
), ),
_buildListRuleFilterActionList(context), if (!isMobile)
Obx(() {
if (controller.isPreviewEnabled.isTrue) {
return RulePreviewBanner(
imagePaths: controller.imagePaths,
message: controller.getActionPreview(context),
isAction: true,
margin: const EdgeInsetsDirectional.only(
top: 8,
bottom: 8,
),
);
} else {
return const SizedBox.shrink();
}
}),
Obx(() {
final listActions = controller
.listEmailRuleFilterActionSelected;
return ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: listActions.length,
padding: const EdgeInsetsDirectional.only(bottom: 8),
itemBuilder: (context, index) {
final action = listActions[index];
final isForwardTo =
action.action?.isForwardTo == true;
final errorValue = action is ForwardActionArguments
? controller.errorForwardEmailValue.value
: controller.errorMailboxSelectedValue.value;
return RuleFilterActionWidget(
isMobile: isMobile,
mailboxSelected: action is MoveMessageActionArguments
? action.mailbox
: null,
errorValue: errorValue,
onActionChangeMobile: () {
controller.selectRuleFilterAction(
context,
action.action,
index,
);
},
onActionChanged: (newAction) {
if (newAction != action.action) {
controller.updateEmailRuleFilterAction(
context,
newAction,
index,
);
}
},
forwardEmailEditingController: isForwardTo
? controller.forwardEmailController
: null,
forwardEmailFocusNode: isForwardTo
? controller.forwardEmailFocusNode
: null,
onChangeForwardEmail: (value) {
controller.updateForwardEmailValue(
appLocalizations,
value,
index,
);
},
actionSelected: action.action,
onTapActionDetailedCallback: () {
FocusScope.of(context).unfocus();
controller.selectMailbox(context, index);
},
onDeleteRuleConditionAction: () {
controller.tapRemoveAction(index);
},
imagePaths: controller.imagePaths,
);
},
);
}),
Obx(() { Obx(() {
if (controller.isShowAddAction.value == true) { if (controller.isShowAddAction.value == true) {
return Container( return Container(
@@ -257,7 +405,10 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
vertical: 25, vertical: 25,
horizontal: isMobile ? 16 : 32, horizontal: isMobile ? 16 : 32,
), ),
onPositiveAction: () => controller.createNewRuleFilter(context), onPositiveAction: () {
FocusScope.of(context).unfocus();
controller.createNewRuleFilter(context);
},
onNegativeAction: () => controller.closeView(context), onNegativeAction: () => controller.closeView(context),
), ),
], ],
@@ -278,117 +429,16 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
} }
} }
Widget _buildListRuleFilterConditionList({ double _getViewWidth(bool isMobile, double screenWidth) {
required BuildContext context, return isMobile ? double.infinity : math.min(screenWidth, 612);
required bool isMobile,
}) {
return Obx(() {
return ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: controller.listRuleCondition.length,
itemBuilder: (context, index) {
final conditionItem =
controller.listRuleConditionValueArguments[index];
return RuleFilterConditionWidget(
key: ValueKey(conditionItem.focusNode),
isMobile: isMobile,
ruleCondition: controller.listRuleCondition[index],
imagePaths: controller.imagePaths,
conditionValueErrorText: conditionItem.errorText,
conditionValueFocusNode: conditionItem.focusNode,
textEditingController: conditionItem.controller,
tapRuleConditionFieldCallback: (value) =>
controller.selectRuleConditionFieldAction(
context,
value,
controller.listRuleCondition[index].field,
isMobile,
index,
),
tapRuleConditionComparatorCallback: (value) =>
controller.selectRuleConditionComparatorAction(
context,
value,
controller.listRuleCondition[index].comparator,
isMobile,
index,
),
conditionValueOnChangeAction: (value) =>
controller.updateConditionValue(context, value, index),
onDeleteRuleConditionAction: () =>
controller.tapRemoveCondition(index),
);
},
);
});
} }
Widget _buildListRuleFilterActionList(BuildContext context) { double _getViewMaxHeight(bool isMobile, double screenHeight) {
return Obx(() { final screenHeightWithoutPadding =
return ListView.builder( screenHeight > 100 ? screenHeight - 100 : screenHeight;
shrinkWrap: true,
primary: false,
itemCount: controller.listEmailRuleFilterActionSelected.length,
padding: const EdgeInsetsDirectional.only(bottom: 8),
itemBuilder: (context, index) {
final currentAction = controller.listEmailRuleFilterActionSelected[index];
String? errorValue;
if (currentAction is ForwardActionArguments) {
errorValue = controller.errorForwardEmailValue.value;
} else {
errorValue = controller.errorMailboxSelectedValue.value;
}
return RuleFilterActionWidget(
responsiveUtils: controller.responsiveUtils,
mailboxSelected: currentAction is MoveMessageActionArguments
? currentAction.mailbox
: null,
errorValue: errorValue,
onActionChangeMobile: () {
controller.selectRuleFilterAction(
context,
currentAction.action,
index,
);
},
onActionChanged: (newAction) {
if (newAction != currentAction.action) {
controller.updateEmailRuleFilterAction(
context,
newAction,
index,
);
}
},
forwardEmailEditingController: currentAction.action == EmailRuleFilterAction.forwardTo
? controller.forwardEmailController
: null,
forwardEmailFocusNode: currentAction.action == EmailRuleFilterAction.forwardTo
? controller.forwardEmailFocusNode
: null,
onChangeForwardEmail: (value) => controller.updateForwardEmailValue(context, value, index),
actionSelected: currentAction.action,
tapActionDetailedCallback: () {
KeyboardUtils.hideKeyboard(context);
controller.selectMailbox(context, index);
},
onDeleteRuleConditionAction: () =>
controller.tapRemoveAction(index),
imagePaths: controller.imagePaths,
);
},
);
});
}
EdgeInsetsGeometry _getPadding(BuildContext context) { return isMobile
if (controller.responsiveUtils.isPortraitMobile(context)) { ? double.infinity
return const EdgeInsetsDirectional.only(start: 8, end: 16); : math.min(screenHeightWithoutPadding, 674);
} else if (controller.responsiveUtils.isLandscapeMobile(context)) {
return const EdgeInsetsDirectional.symmetric(horizontal: 24);
} else {
return const EdgeInsetsDirectional.symmetric(horizontal: 32);
}
} }
} }
@@ -1,6 +0,0 @@
import 'package:flutter/material.dart';
class RuleConditionCombinerBottomSheetStyles {
static const Color defaultBgColor = Colors.white;
static const double defaultIconRightPadding = 12.0;
}
@@ -1,10 +1,10 @@
import 'package:core/core.dart'; import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart'; import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class RuleFilterActionDetailed extends StatelessWidget { class RuleFilterActionDetailed extends StatelessWidget {
@@ -12,10 +12,10 @@ class RuleFilterActionDetailed extends StatelessWidget {
final EmailRuleFilterAction? actionType; final EmailRuleFilterAction? actionType;
final PresentationMailbox? mailboxSelected; final PresentationMailbox? mailboxSelected;
final String? errorValue; final String? errorValue;
final Function()? tapActionDetailedCallback;
final TextEditingController? forwardEmailEditingController; final TextEditingController? forwardEmailEditingController;
final FocusNode? forwardEmailFocusNode; final FocusNode? forwardEmailFocusNode;
final OnChangeFilterInputAction? forwardEmailOnChangeAction; final OnTextChange? forwardEmailOnChangeAction;
final VoidCallback? onTapActionDetailedCallback;
const RuleFilterActionDetailed({ const RuleFilterActionDetailed({
Key? key, Key? key,
@@ -23,24 +23,23 @@ class RuleFilterActionDetailed extends StatelessWidget {
this.actionType, this.actionType,
this.mailboxSelected, this.mailboxSelected,
this.errorValue, this.errorValue,
this.tapActionDetailedCallback,
this.forwardEmailEditingController, this.forwardEmailEditingController,
this.forwardEmailFocusNode, this.forwardEmailFocusNode,
this.forwardEmailOnChangeAction, this.forwardEmailOnChangeAction,
this.onTapActionDetailedCallback,
}) : super(key: key); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final borderColor = errorValue?.isNotEmpty == true ? AppColor.colorInputBorderErrorVerifyName : AppColor.colorInputBorderCreateMailbox;
switch (actionType) { switch (actionType) {
case EmailRuleFilterAction.moveMessage: case EmailRuleFilterAction.moveMessage:
return RuleFilterButtonField<PresentationMailbox>( return RuleFilterButtonField<PresentationMailbox>(
value: mailboxSelected, value: mailboxSelected,
imagePaths: imagePaths, imagePaths: imagePaths,
borderColor: borderColor, borderColor: errorValue?.isNotEmpty == true
onTapActionCallback: (value) { ? AppColor.redFF3347
tapActionDetailedCallback!(); : AppColor.m3Neutral90,
}, onTapActionCallback: (_) => onTapActionDetailedCallback?.call(),
); );
case EmailRuleFilterAction.forwardTo: case EmailRuleFilterAction.forwardTo:
return DefaultInputFieldWidget( return DefaultInputFieldWidget(
@@ -7,22 +7,23 @@ import 'package:tmail_ui_user/features/base/widget/default_field/default_input_f
import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart'; import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnActionChanged = Function(EmailRuleFilterAction? action);
class RuleFilterActionRow extends StatelessWidget { class RuleFilterActionRow extends StatelessWidget {
final List<EmailRuleFilterAction> actionList; final List<EmailRuleFilterAction> actionList;
final ImagePaths imagePaths; final ImagePaths imagePaths;
final OnDeleteRuleConditionAction onDeleteRuleConditionAction; final OnDeleteRuleConditionAction onDeleteRuleConditionAction;
final EmailRuleFilterAction? actionSelected; final EmailRuleFilterAction? actionSelected;
final Function(EmailRuleFilterAction?)? onActionChanged; final OnActionChanged? onActionChanged;
final PresentationMailbox? mailboxSelected; final PresentationMailbox? mailboxSelected;
final String? errorValue; final String? errorValue;
final Function()? tapActionDetailedCallback;
final TextEditingController? forwardEmailEditingController; final TextEditingController? forwardEmailEditingController;
final FocusNode? forwardEmailFocusNode; final FocusNode? forwardEmailFocusNode;
final OnChangeFilterInputAction? onChangeForwardEmail; final OnTextChange? onChangeForwardEmail;
final VoidCallback? onTapActionDetailedCallback;
const RuleFilterActionRow({ const RuleFilterActionRow({
Key? key, Key? key,
@@ -33,7 +34,7 @@ class RuleFilterActionRow extends StatelessWidget {
this.onActionChanged, this.onActionChanged,
this.mailboxSelected, this.mailboxSelected,
this.errorValue, this.errorValue,
this.tapActionDetailedCallback, this.onTapActionDetailedCallback,
this.forwardEmailEditingController, this.forwardEmailEditingController,
this.forwardEmailFocusNode, this.forwardEmailFocusNode,
this.onChangeForwardEmail, this.onChangeForwardEmail,
@@ -41,15 +42,11 @@ class RuleFilterActionRow extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final supportedAction = actionList
.where((action) => action.isSupported)
.toList();
return Row( return Row(
children: [ children: [
Expanded( Expanded(
child: DropDownButtonWidget<EmailRuleFilterAction>( child: DropDownButtonWidget<EmailRuleFilterAction>(
items: supportedAction, items: actionList,
itemSelected: actionSelected, itemSelected: actionSelected,
onChanged: (newAction) => onActionChanged!(newAction), onChanged: (newAction) => onActionChanged!(newAction),
supportSelectionIcon: true, supportSelectionIcon: true,
@@ -57,6 +54,7 @@ class RuleFilterActionRow extends StatelessWidget {
labelTextStyle: ThemeUtils.textStyleBodyBody3( labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black, color: Colors.black,
), ),
heightItem: 40,
hintTextStyle: ThemeUtils.textStyleBodyBody3( hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400, color: AppColor.steelGray400,
), ),
@@ -85,11 +83,11 @@ class RuleFilterActionRow extends StatelessWidget {
borderColor: errorValue?.isNotEmpty == true borderColor: errorValue?.isNotEmpty == true
? AppColor.redFF3347 ? AppColor.redFF3347
: AppColor.m3Neutral90, : AppColor.m3Neutral90,
onTapActionCallback: (_) => tapActionDetailedCallback?.call(), onTapActionCallback: (_) => onTapActionDetailedCallback?.call(),
), ),
), ),
] ]
else if (actionSelected == EmailRuleFilterAction.forwardTo) else if (actionSelected?.isForwardTo == true)
Expanded( Expanded(
child: DefaultInputFieldWidget( child: DefaultInputFieldWidget(
errorText: errorValue, errorText: errorValue,
@@ -1,34 +1,35 @@
import 'package:core/core.dart'; import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_detailed_builder.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_detailed_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class RuleFilterActionRowMobile extends StatelessWidget { class RuleFilterActionRowMobile extends StatelessWidget {
final ImagePaths imagePaths; final ImagePaths imagePaths;
final EmailRuleFilterAction? actionSelected; final EmailRuleFilterAction? actionSelected;
final Function()? tapActionCallback;
final PresentationMailbox? mailboxSelected; final PresentationMailbox? mailboxSelected;
final String? errorValue; final String? errorValue;
final Function()? tapActionDetailedCallback;
final TextEditingController? forwardEmailEditingController; final TextEditingController? forwardEmailEditingController;
final FocusNode? forwardEmailFocusNode; final FocusNode? forwardEmailFocusNode;
final OnChangeFilterInputAction? onChangeForwardEmail; final OnTextChange? onChangeForwardEmail;
final VoidCallback? onTapActionDetailedCallback;
final VoidCallback? onTapActionCallback;
const RuleFilterActionRowMobile({ const RuleFilterActionRowMobile({
Key? key, Key? key,
required this.imagePaths, required this.imagePaths,
this.actionSelected, this.actionSelected,
this.tapActionCallback,
this.mailboxSelected, this.mailboxSelected,
this.errorValue, this.errorValue,
this.tapActionDetailedCallback,
this.forwardEmailEditingController, this.forwardEmailEditingController,
this.forwardEmailFocusNode, this.forwardEmailFocusNode,
this.onChangeForwardEmail, this.onChangeForwardEmail,
this.onTapActionDetailedCallback,
this.onTapActionCallback,
}) : super(key: key); }) : super(key: key);
@override @override
@@ -39,14 +40,12 @@ class RuleFilterActionRowMobile extends StatelessWidget {
RuleFilterButtonField<EmailRuleFilterAction>( RuleFilterButtonField<EmailRuleFilterAction>(
value: actionSelected, value: actionSelected,
imagePaths: imagePaths, imagePaths: imagePaths,
onTapActionCallback: (value) { onTapActionCallback: (_) => onTapActionCallback?.call(),
tapActionCallback!();
},
hintText: AppLocalizations.of(context).selectAction, hintText: AppLocalizations.of(context).selectAction,
), ),
actionSelected == EmailRuleFilterAction.moveMessage actionSelected == EmailRuleFilterAction.moveMessage
? Container( ? Container(
alignment: Alignment.centerLeft, alignment: AlignmentDirectional.centerStart,
padding: const EdgeInsets.symmetric(vertical: 12), padding: const EdgeInsets.symmetric(vertical: 12),
child: Text( child: Text(
AppLocalizations.of(context).toFolder, AppLocalizations.of(context).toFolder,
@@ -60,17 +59,17 @@ class RuleFilterActionRowMobile extends StatelessWidget {
), ),
) )
: SizedBox( : SizedBox(
height: actionSelected == EmailRuleFilterAction.forwardTo ? 12 : 0, height: actionSelected?.isForwardTo == true ? 12 : 0,
), ),
RuleFilterActionDetailed( RuleFilterActionDetailed(
imagePaths: imagePaths, imagePaths: imagePaths,
actionType: actionSelected, actionType: actionSelected,
mailboxSelected: mailboxSelected, mailboxSelected: mailboxSelected,
errorValue: errorValue, errorValue: errorValue,
tapActionDetailedCallback: tapActionDetailedCallback,
forwardEmailEditingController: forwardEmailEditingController, forwardEmailEditingController: forwardEmailEditingController,
forwardEmailFocusNode: forwardEmailFocusNode, forwardEmailFocusNode: forwardEmailFocusNode,
forwardEmailOnChangeAction: onChangeForwardEmail, forwardEmailOnChangeAction: onChangeForwardEmail,
onTapActionDetailedCallback: onTapActionDetailedCallback,
), ),
], ],
); );
@@ -1,49 +1,46 @@
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/utils/responsive_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_row_builder.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_row_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_row_mobile_builder.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_action_row_mobile_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart';
class RuleFilterActionWidget extends StatelessWidget { class RuleFilterActionWidget extends StatelessWidget {
final ResponsiveUtils responsiveUtils;
final ImagePaths imagePaths; final ImagePaths imagePaths;
final bool isMobile;
final OnDeleteRuleConditionAction onDeleteRuleConditionAction; final OnDeleteRuleConditionAction onDeleteRuleConditionAction;
final EmailRuleFilterAction? actionSelected; final EmailRuleFilterAction? actionSelected;
final Function(EmailRuleFilterAction?)? onActionChanged;
final Function()? onActionChangeMobile;
final PresentationMailbox? mailboxSelected; final PresentationMailbox? mailboxSelected;
final String? errorValue; final String? errorValue;
final Function()? tapActionDetailedCallback; final VoidCallback? onTapActionDetailedCallback;
final TextEditingController? forwardEmailEditingController; final TextEditingController? forwardEmailEditingController;
final FocusNode? forwardEmailFocusNode; final FocusNode? forwardEmailFocusNode;
final OnChangeFilterInputAction? onChangeForwardEmail; final OnTextChange? onChangeForwardEmail;
final OnActionChanged? onActionChanged;
final VoidCallback? onActionChangeMobile;
const RuleFilterActionWidget({ const RuleFilterActionWidget({
Key? key, Key? key,
required this.responsiveUtils,
required this.imagePaths, required this.imagePaths,
required this.isMobile,
required this.onDeleteRuleConditionAction, required this.onDeleteRuleConditionAction,
this.actionSelected, this.actionSelected,
this.onActionChanged,
this.mailboxSelected, this.mailboxSelected,
this.errorValue, this.errorValue,
this.tapActionDetailedCallback,
this.forwardEmailEditingController, this.forwardEmailEditingController,
this.forwardEmailFocusNode, this.forwardEmailFocusNode,
this.onChangeForwardEmail, this.onChangeForwardEmail,
this.onActionChangeMobile, this.onActionChangeMobile,
this.onTapActionDetailedCallback,
this.onActionChanged,
}) : super(key: key); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isMobile = responsiveUtils.isMobile(context);
if (!isMobile) { if (!isMobile) {
return Container( return Container(
padding: const EdgeInsetsDirectional.only(start: 12), padding: const EdgeInsetsDirectional.only(start: 12),
@@ -55,17 +52,19 @@ class RuleFilterActionWidget extends StatelessWidget {
height: 72, height: 72,
alignment: Alignment.center, alignment: Alignment.center,
child: RuleFilterActionRow( child: RuleFilterActionRow(
actionList: EmailRuleFilterAction.values, actionList: EmailRuleFilterAction.values
.where((action) => action.isSupported)
.toList(),
actionSelected: actionSelected, actionSelected: actionSelected,
onActionChanged: onActionChanged, onActionChanged: onActionChanged,
mailboxSelected: mailboxSelected, mailboxSelected: mailboxSelected,
errorValue: errorValue, errorValue: errorValue,
tapActionDetailedCallback: tapActionDetailedCallback,
imagePaths: imagePaths, imagePaths: imagePaths,
onDeleteRuleConditionAction: onDeleteRuleConditionAction, onDeleteRuleConditionAction: onDeleteRuleConditionAction,
forwardEmailEditingController: forwardEmailEditingController, forwardEmailEditingController: forwardEmailEditingController,
forwardEmailFocusNode: forwardEmailFocusNode, forwardEmailFocusNode: forwardEmailFocusNode,
onChangeForwardEmail: onChangeForwardEmail, onChangeForwardEmail: onChangeForwardEmail,
onTapActionDetailedCallback: onTapActionDetailedCallback,
), ),
); );
} else { } else {
@@ -92,39 +91,38 @@ class RuleFilterActionWidget extends StatelessWidget {
], ],
), ),
child: Builder( child: Builder(
builder: (context) { builder: (context) {
SlidableController? slideController = Slidable.of(context); SlidableController? slideController = Slidable.of(context);
return ValueListenableBuilder<int>( return ValueListenableBuilder<int>(
valueListenable: slideController?.direction ?? ValueNotifier<int>(0), valueListenable: slideController?.direction ?? ValueNotifier<int>(0),
builder: (context, value, _) { builder: (context, value, _) {
final borderRadius = value != -1 return Container(
? BorderRadius.circular(10) padding: const EdgeInsetsDirectional.all(8),
: const BorderRadius.only( decoration: BoxDecoration(
bottomLeft: Radius.circular(10), color: AppColor.lightGrayF9FAFB,
topLeft: Radius.circular(10), borderRadius: value != -1
); ? BorderRadius.circular(10)
return Container( : const BorderRadius.only(
padding: const EdgeInsetsDirectional.all(8), bottomLeft: Radius.circular(10),
decoration: BoxDecoration( topLeft: Radius.circular(10),
color: AppColor.lightGrayF9FAFB, ),
borderRadius: borderRadius, ),
), alignment: Alignment.center,
alignment: Alignment.center, child: RuleFilterActionRowMobile(
child: RuleFilterActionRowMobile( imagePaths: imagePaths,
imagePaths: imagePaths, actionSelected: actionSelected,
actionSelected: actionSelected, mailboxSelected: mailboxSelected,
mailboxSelected: mailboxSelected, errorValue: errorValue,
errorValue: errorValue, forwardEmailEditingController: forwardEmailEditingController,
tapActionDetailedCallback: tapActionDetailedCallback, forwardEmailFocusNode: forwardEmailFocusNode,
forwardEmailEditingController: forwardEmailEditingController, onChangeForwardEmail: onChangeForwardEmail,
forwardEmailFocusNode: forwardEmailFocusNode, onTapActionCallback: onActionChangeMobile,
onChangeForwardEmail: onChangeForwardEmail, onTapActionDetailedCallback: onTapActionDetailedCallback,
tapActionCallback: onActionChangeMobile, ),
), );
); },
}, );
); },
}
), ),
), ),
); );
@@ -7,7 +7,6 @@ import 'package:rule_filter/rule_filter/rule_condition.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart'; import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart';
import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart'; import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -21,7 +20,7 @@ class RuleFilterConditionRow extends StatelessWidget {
final String? conditionValueErrorText; final String? conditionValueErrorText;
final TextEditingController textEditingController; final TextEditingController textEditingController;
final FocusNode? conditionValueFocusNode; final FocusNode? conditionValueFocusNode;
final OnChangeFilterInputAction? conditionValueOnChangeAction; final OnTextChange? conditionValueOnChangeAction;
const RuleFilterConditionRow({ const RuleFilterConditionRow({
Key? key, Key? key,
@@ -3,12 +3,11 @@ import 'package:core/presentation/resources/image_paths.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart'; import 'package:rule_filter/rule_filter/rule_condition.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_input_field_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_button_field.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_row_builder.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_condition_row_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart';
typedef OnChangeFilterInputAction = Function(String? value);
class RuleFilterConditionWidget extends StatelessWidget { class RuleFilterConditionWidget extends StatelessWidget {
final bool isMobile; final bool isMobile;
final RuleCondition ruleCondition; final RuleCondition ruleCondition;
@@ -17,7 +16,7 @@ class RuleFilterConditionWidget extends StatelessWidget {
final OnRuleTapActionCallback tapRuleConditionComparatorCallback; final OnRuleTapActionCallback tapRuleConditionComparatorCallback;
final String? conditionValueErrorText; final String? conditionValueErrorText;
final FocusNode? conditionValueFocusNode; final FocusNode? conditionValueFocusNode;
final OnChangeFilterInputAction? conditionValueOnChangeAction; final OnTextChange? conditionValueOnChangeAction;
final ImagePaths imagePaths; final ImagePaths imagePaths;
final OnDeleteRuleConditionAction onDeleteRuleConditionAction; final OnDeleteRuleConditionAction onDeleteRuleConditionAction;
@@ -37,6 +36,19 @@ class RuleFilterConditionWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final conditionRowWidget = RuleFilterConditionRow(
isMobile: isMobile,
ruleCondition: ruleCondition,
tapRuleConditionFieldCallback: tapRuleConditionFieldCallback,
tapRuleConditionComparatorCallback: tapRuleConditionComparatorCallback,
conditionValueErrorText: conditionValueErrorText,
textEditingController: textEditingController,
conditionValueFocusNode: conditionValueFocusNode,
conditionValueOnChangeAction: conditionValueOnChangeAction,
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
imagePaths: imagePaths,
);
if (isMobile) { if (isMobile) {
return Padding( return Padding(
padding: const EdgeInsetsDirectional.only(top: 8), padding: const EdgeInsetsDirectional.only(top: 8),
@@ -66,35 +78,23 @@ class RuleFilterConditionWidget extends StatelessWidget {
return ValueListenableBuilder<int>( return ValueListenableBuilder<int>(
valueListenable: slideController?.direction ?? ValueNotifier<int>(0), valueListenable: slideController?.direction ?? ValueNotifier<int>(0),
builder: (context, value, _) { builder: (context, value, _) {
final borderRadius = value != -1
? BorderRadius.circular(10)
: const BorderRadius.only(
bottomLeft: Radius.circular(10),
topLeft: Radius.circular(10),
);
return Container( return Container(
padding: const EdgeInsetsDirectional.all(8), padding: const EdgeInsetsDirectional.all(8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColor.lightGrayF9FAFB, color: AppColor.lightGrayF9FAFB,
borderRadius: borderRadius, borderRadius: value != -1
? BorderRadius.circular(10)
: const BorderRadius.only(
bottomLeft: Radius.circular(10),
topLeft: Radius.circular(10),
),
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: RuleFilterConditionRow( child: conditionRowWidget,
isMobile: isMobile,
ruleCondition: ruleCondition,
tapRuleConditionFieldCallback: tapRuleConditionFieldCallback,
tapRuleConditionComparatorCallback: tapRuleConditionComparatorCallback,
conditionValueErrorText: conditionValueErrorText,
textEditingController: textEditingController,
conditionValueFocusNode: conditionValueFocusNode,
conditionValueOnChangeAction: conditionValueOnChangeAction,
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
imagePaths: imagePaths,
),
); );
} }
); );
} },
), ),
), ),
); );
@@ -107,18 +107,7 @@ class RuleFilterConditionWidget extends StatelessWidget {
borderRadius: BorderRadius.all(Radius.circular(10)), borderRadius: BorderRadius.all(Radius.circular(10)),
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: RuleFilterConditionRow( child: conditionRowWidget,
isMobile: isMobile,
ruleCondition: ruleCondition,
tapRuleConditionFieldCallback: tapRuleConditionFieldCallback,
tapRuleConditionComparatorCallback: tapRuleConditionComparatorCallback,
conditionValueErrorText: conditionValueErrorText,
textEditingController: textEditingController,
conditionValueFocusNode: conditionValueFocusNode,
conditionValueOnChangeAction: conditionValueOnChangeAction,
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
imagePaths: imagePaths,
),
); );
} }
} }
@@ -25,6 +25,24 @@ class RuleFilterTitle extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final appLocalizations = AppLocalizations.of(context); final appLocalizations = AppLocalizations.of(context);
final titleBeforeWidget = Text(
appLocalizations.conditionTitleRulesFilterBeforeCombiner,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
);
final titleAfterWidget = Text(
appLocalizations.conditionTitleRulesFilterAfterCombiner,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
);
if (isMobile) { if (isMobile) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -32,14 +50,7 @@ class RuleFilterTitle extends StatelessWidget {
children: [ children: [
Row( Row(
children: [ children: [
Text( titleBeforeWidget,
appLocalizations.conditionTitleRulesFilterBeforeCombiner,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
Expanded( Expanded(
child: Container( child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
@@ -54,14 +65,7 @@ class RuleFilterTitle extends StatelessWidget {
], ],
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( titleAfterWidget,
appLocalizations.conditionTitleRulesFilterAfterCombiner,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
)
], ],
); );
} }
@@ -71,14 +75,7 @@ class RuleFilterTitle extends StatelessWidget {
runAlignment: WrapAlignment.center, runAlignment: WrapAlignment.center,
runSpacing: 8, runSpacing: 8,
children: [ children: [
Text( titleBeforeWidget,
appLocalizations.conditionTitleRulesFilterBeforeCombiner,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
width: 158, width: 158,
@@ -86,6 +83,7 @@ class RuleFilterTitle extends StatelessWidget {
items: ConditionCombiner.values, items: ConditionCombiner.values,
itemSelected: conditionCombinerType, itemSelected: conditionCombinerType,
supportSelectionIcon: true, supportSelectionIcon: true,
heightItem: 40,
labelTextStyle: ThemeUtils.textStyleBodyBody3( labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black, color: Colors.black,
), ),
@@ -95,14 +93,7 @@ class RuleFilterTitle extends StatelessWidget {
onChanged: onTapActionCallback, onChanged: onTapActionCallback,
), ),
), ),
Text( titleAfterWidget,
appLocalizations.conditionTitleRulesFilterAfterCombiner,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
)
], ],
); );
} }
@@ -0,0 +1,60 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter/material.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class RuleFilterTitleWithPreviewButton extends StatelessWidget {
final ImagePaths imagePaths;
final bool isPreviewEnabled;
final VoidCallback onTogglePreviewAction;
const RuleFilterTitleWithPreviewButton({
super.key,
required this.imagePaths,
required this.isPreviewEnabled,
required this.onTogglePreviewAction,
});
@override
Widget build(BuildContext context) {
final appLocalizations = AppLocalizations.of(context);
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Row(
children: [
Expanded(
child: Text(
appLocalizations.condition,
style: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
),
TMailButtonWidget(
text: isPreviewEnabled
? appLocalizations.hide
: appLocalizations.preview,
icon: isPreviewEnabled ? imagePaths.icEyeOff : imagePaths.icEye,
iconSize: 12,
iconColor: AppColor.primaryMain,
backgroundColor: Colors.transparent,
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8),
textStyle: ThemeUtils.textStyleInter400.copyWith(
fontSize: 11,
height: 16 / 11,
letterSpacing: 0.5,
color: AppColor.primaryMain,
),
onTapActionCallback: onTogglePreviewAction,
)
],
),
);
}
}
@@ -0,0 +1,79 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class RulePreviewBanner extends StatelessWidget {
final ImagePaths imagePaths;
final String message;
final bool isAction;
final EdgeInsetsGeometry? margin;
const RulePreviewBanner({
super.key,
required this.imagePaths,
required this.message,
required this.isAction,
this.margin,
});
@override
Widget build(BuildContext context) {
final appLocalizations = AppLocalizations.of(context);
return Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(8)),
color: isAction ? AppColor.lightGreenF0FDF4 : AppColor.lightBlueEFF6FF,
border: Border.all(
color:
isAction ? AppColor.lightGreenBBF7D0 : AppColor.lightBlueBFDBFE,
),
),
padding: const EdgeInsets.all(4),
margin: margin,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SvgPicture.asset(
isAction ? imagePaths.icCheck : imagePaths.icInfoCircleOutline,
width: 20,
height: 20,
colorFilter: isAction
? AppColor.green166534.asFilter()
: AppColor.m3SysLight.asFilter(),
fit: BoxFit.fill,
),
const SizedBox(width: 8),
Expanded(
child: Text.rich(
TextSpan(
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 20 / 14,
letterSpacing: 0.1,
color: isAction ? AppColor.green166534 : AppColor.m3SysLight,
),
children: [
TextSpan(
text: '${appLocalizations.preview}:',
style: ThemeUtils.textStyleInter700().copyWith(
fontSize: 14,
height: 20 / 14,
letterSpacing: 0.1,
color:
isAction ? AppColor.green166534 : AppColor.m3SysLight,
),
),
TextSpan(text: ' $message'),
],
),
),
),
],
),
);
}
}
+24
View File
@@ -4765,5 +4765,29 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"preview": "Preview",
"@preview": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"ruleFilterConditionPreviewMessage": "{conditionCombinerName} of the conditions: {conditionValue}",
"@ruleFilterConditionPreviewMessage": {
"type": "text",
"placeholders_order": [
"conditionCombinerName",
"conditionValue"
],
"placeholders": {
"conditionCombinerName": {},
"conditionValue": {}
}
},
"actions": "Actions",
"@actions": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
@@ -5034,4 +5034,29 @@ class AppLocalizations {
name: 'createRule', name: 'createRule',
); );
} }
String get preview {
return Intl.message(
'Preview',
name: 'preview',
);
}
String ruleFilterConditionPreviewMessage(String conditionCombinerName, String conditionValue) {
return Intl.message(
'$conditionCombinerName of the conditions: $conditionValue',
name: 'ruleFilterConditionPreviewMessage',
args: [
conditionCombinerName,
conditionValue,
],
);
}
String get actions {
return Intl.message(
'Actions',
name: 'actions',
);
}
} }