TF-4004 Apply new design for create rule view on mobile

This commit is contained in:
dab246
2025-09-08 16:35:06 +07:00
committed by Dat H. Pham
parent 8c3c7b1feb
commit a0123c41b0
19 changed files with 620 additions and 1105 deletions
@@ -6,7 +6,6 @@ import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/c
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/context_menu/context_item_rule_condition_field_action.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/context_menu/context_item_rule_condition_field_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/context_menu/context_item_rule_filter_action.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/context_menu/context_item_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/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_condition_type.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/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -37,7 +36,7 @@ extension SelectRuleActionFieldExtension on RulesFilterCreatorController {
itemActions: contextMenuActions, itemActions: contextMenuActions,
onContextMenuActionClick: (menuAction) { onContextMenuActionClick: (menuAction) {
popBack(); popBack();
selectConditionCombiner(menuAction.action); updateConditionCombiner(menuAction.action);
}, },
); );
} }
@@ -46,10 +45,10 @@ extension SelectRuleActionFieldExtension on RulesFilterCreatorController {
BuildContext context, BuildContext context,
Field? currentField, Field? currentField,
Field selectedField, Field selectedField,
RuleFilterConditionScreenType screenType, bool isMobile,
int index, int index,
) { ) {
if (screenType == RuleFilterConditionScreenType.mobile) { if (isMobile) {
unFocusAllInputField(); unFocusAllInputField();
final contextMenuActions = Field.values.map((field) { final contextMenuActions = Field.values.map((field) {
@@ -78,10 +77,10 @@ extension SelectRuleActionFieldExtension on RulesFilterCreatorController {
BuildContext context, BuildContext context,
Comparator? currentComparator, Comparator? currentComparator,
Comparator selectedComparator, Comparator selectedComparator,
RuleFilterConditionScreenType screenType, bool isMobile,
int index, int index,
) { ) {
if (screenType == RuleFilterConditionScreenType.mobile) { if (isMobile) {
unFocusAllInputField(); unFocusAllInputField();
final contextMenuActions = Comparator.values.map((comparator) { final contextMenuActions = Comparator.values.map((comparator) {
@@ -1,5 +1,4 @@
enum RuleFilterConditionScreenType { enum RuleFilterConditionScreenType {
mobile, mobile,
tablet,
desktop desktop
} }
@@ -34,6 +34,7 @@ import 'package:tmail_ui_user/features/manage_account/domain/model/edit_email_ru
import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_rules_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_rules_state.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_rules_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_rules_interactor.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/list_rule_filter_action_argument_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/creator_action_type.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/creator_action_type.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/model/rule_filter_action_arguments.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_action_arguments.dart';
@@ -618,12 +619,27 @@ class RulesFilterCreatorController extends BaseMailboxController {
listRuleConditionValueArguments.removeAt(ruleConditionIndex); listRuleConditionValueArguments.removeAt(ruleConditionIndex);
} }
void selectConditionCombiner(ConditionCombiner? combinerType) { void selectConditionCombiner({
if (combinerType != null) { required BuildContext context,
conditionCombinerType.value = combinerType; ConditionCombiner? combinerType,
bool isMobile = false,
}) {
FocusScope.of(context).unfocus();
if (isMobile) {
selectRuleConditionCombinerAction(
context,
conditionCombinerType.value ?? ConditionCombiner.AND,
);
} else if (combinerType != null) {
updateConditionCombiner(combinerType);
} }
} }
void updateConditionCombiner(ConditionCombiner? newConditionCombiner) {
conditionCombinerType.value = newConditionCombiner;
}
void tapAddAction() { void tapAddAction() {
listEmailRuleFilterActionSelected.add(RuleFilterActionArguments.emptyAction()); listEmailRuleFilterActionSelected.add(RuleFilterActionArguments.emptyAction());
if (listEmailRuleFilterActionSelected.length >= maxCountAction) { if (listEmailRuleFilterActionSelected.length >= maxCountAction) {
@@ -3,22 +3,17 @@ import 'dart:math' as math;
import 'package:core/core.dart'; import 'package:core/core.dart';
import 'package:core/presentation/views/dialog/confirm_dialog_button.dart'; import 'package:core/presentation/views/dialog/confirm_dialog_button.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:rule_filter/rule_filter/rule_condition_group.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/base/widget/pop_back_barrier_widget.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/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/model/rule_filter_condition_type.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_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/rules_filter_input_field_builder.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> {
@@ -32,17 +27,18 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final responsiveUtil = controller.responsiveUtils; final responsiveUtil = controller.responsiveUtils;
final isMobile = responsiveUtil.isMobile(context); final isMobile = responsiveUtil.isMobile(context);
final focusScope = FocusScope.of(context);
final currentScreenHeight = responsiveUtil.getSizeScreenHeight(context); final currentScreenHeight = responsiveUtil.getSizeScreenHeight(context);
final currentScreenWidth = responsiveUtil.getSizeScreenWidth(context); final currentScreenWidth = responsiveUtil.getSizeScreenWidth(context);
if (!isMobile) { Widget bodyWidget = Container(
return Center( decoration: BoxDecoration(
child: Container( color: Colors.white,
decoration: BoxDecoration( borderRadius: isMobile
color: Colors.white, ? null
borderRadius: const BorderRadius.all(Radius.circular(16)), : const BorderRadius.all(Radius.circular(16)),
boxShadow: [ boxShadow: isMobile
? null
: [
BoxShadow( BoxShadow(
color: Colors.black.withValues(alpha: 0.08), color: Colors.black.withValues(alpha: 0.08),
blurRadius: 24, blurRadius: 24,
@@ -53,400 +49,250 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
blurRadius: 2, blurRadius: 2,
), ),
], ],
), ),
width: math.min( width: isMobile
? double.infinity :
math.min(
currentScreenWidth, currentScreenWidth,
612, 612,
), ),
constraints: BoxConstraints( constraints: BoxConstraints(
maxHeight: math.min( maxHeight: isMobile
currentScreenHeight - 100, ? double.infinity
674, : math.min(
), currentScreenHeight - 100,
674,
), ),
clipBehavior: Clip.antiAlias, ),
child: _buildRulesFilterFormOnDesktop(context), clipBehavior: isMobile ? Clip.none : Clip.antiAlias,
child: _buildRulesFilterForm(context, isMobile),
);
if (isMobile) {
bodyWidget = Scaffold(
backgroundColor: Colors.white,
body: GestureDetector(
onTap: FocusScope.of(context).unfocus,
child: SafeArea(child: bodyWidget),
), ),
); );
} else {
bodyWidget = Center(child: bodyWidget);
} }
return ResponsiveWidget( return bodyWidget;
responsiveUtils: responsiveUtil,
mobile: Scaffold(
backgroundColor:
PlatformInfo.isWeb ? Colors.black.withAlpha(24) : Colors.black38,
body: PopBackBarrierWidget(
child: SafeArea(
bottom: false,
left: false,
right: false,
child: GestureDetector(
onTap: focusScope.unfocus,
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.vertical(
top: Radius.circular(16),
),
color: Colors.white,
),
margin: EdgeInsets.only(top: PlatformInfo.isWeb ? 70 : 0),
child: SafeArea(
child: _buildRulesFilterFormOnMobile(context),
),
),
),
),
),
),
tablet: Scaffold(
backgroundColor: Colors.black.withAlpha(24),
body: Center(
child: GestureDetector(
onTap: focusScope.unfocus,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(16)),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.08),
blurRadius: 24,
offset: const Offset(0, 2),
),
BoxShadow(
color: Colors.black.withValues(alpha: 0.08),
blurRadius: 2,
),
],
),
width: math.min(
currentScreenWidth,
612,
),
constraints: BoxConstraints(
maxHeight: math.min(
currentScreenHeight - 100,
674,
),
),
clipBehavior: Clip.antiAlias,
child: _buildRulesFilterFormOnDesktop(context),
),
),
),
),
);
} }
Widget _buildRulesFilterFormOnDesktop(BuildContext context) { Widget _buildRulesFilterForm(BuildContext context, bool isMobile) {
final appLocalizations = AppLocalizations.of(context); final appLocalizations = AppLocalizations.of(context);
return Stack( Widget formWidget = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Column( if (!isMobile)
crossAxisAlignment: CrossAxisAlignment.start, Container(
children: [ padding: const EdgeInsets.only(top: 24, bottom: 12),
Container( alignment: Alignment.center,
padding: const EdgeInsets.only(top: 24, bottom: 12), child: Obx(
alignment: Alignment.center, () => Text(
child: Obx( controller.actionType.value.getTitle(appLocalizations),
() => Text( textAlign: TextAlign.center,
controller.actionType.value.getTitle(appLocalizations), style: Theme.of(context).textTheme.headlineSmall?.copyWith(
textAlign: TextAlign.center, color: AppColor.m3SurfaceBackground,
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
color: AppColor.m3SurfaceBackground,
),
), ),
), ),
), ),
Expanded( )
child: SingleChildScrollView( else
physics: const ClampingScrollPhysics(), Container(
child: Padding( height: 64,
padding: const EdgeInsets.symmetric(horizontal: 32), padding: _getPadding(context),
child: Column( child: Stack(
crossAxisAlignment: CrossAxisAlignment.start, alignment: Alignment.center,
children: [ children: [
Obx( PositionedDirectional(
start: 0,
child: TMailButtonWidget.fromIcon(
icon: controller.imagePaths.icArrowBack,
tooltipMessage: appLocalizations.back,
backgroundColor: Colors.transparent,
onTapActionCallback: () => controller.closeView(context),
),
),
Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 50),
child: Obx(
() => Text(
controller.actionType.value.getTitle(appLocalizations),
textAlign: TextAlign.center,
style: ThemeUtils.textStyleM3BodyLarge.copyWith(
color: AppColor.m3SurfaceBackground,
),
),
),
),
),
],
),
),
Expanded(
child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: isMobile ? 16 : 32,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
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,
isLabelHasColon: false, isLabelHasColon: false,
labelStyle: ThemeUtils.textStyleInter600().copyWith( labelStyle: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14, fontSize: 14,
height: 18 / 14, height: 18 / 14,
color: Colors.black, color: Colors.black,
),
runSpacing: 16,
inputFieldMaxWidth: double.infinity,
onTextChange: (value) =>
controller.updateRuleName(context, value),
),
), ),
Padding( runSpacing: 16,
padding: const EdgeInsets.symmetric( inputFieldMaxWidth: double.infinity,
vertical: 24, onTextChange: (value) =>
), controller.updateRuleName(context, value),
child: Text( ),
appLocalizations.condition, ),
style: ThemeUtils.textStyleInter600().copyWith( Padding(
fontSize: 14, padding: const EdgeInsets.symmetric(
height: 18 / 14, vertical: 24,
color: Colors.black, ),
), child: Text(
), appLocalizations.condition,
style: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
), ),
Obx( ),
),
Obx(
() => RuleFilterTitle( () => RuleFilterTitle(
conditionCombinerType: conditionCombinerType: controller.conditionCombinerType.value,
controller.conditionCombinerType.value, imagePaths: controller.imagePaths,
responsiveUtils: controller.responsiveUtils, isMobile: isMobile,
tapActionCallback: (value) => onTapActionCallback: (value) =>
controller.selectConditionCombiner(value), controller.selectConditionCombiner(
ruleFilterConditionScreenType: context: context,
RuleFilterConditionScreenType.desktop, combinerType: value,
), isMobile: isMobile,
),
),
),
const SizedBox(height: 8),
_buildListRuleFilterConditionList(
context: context,
isMobile: isMobile,
),
Container(
constraints: const BoxConstraints(minWidth: 161),
height: 36,
margin: const EdgeInsetsDirectional.only(top: 12),
child: ConfirmDialogButton(
label: AppLocalizations.of(context).addACondition,
backgroundColor: Colors.white,
textColor: AppColor.primaryMain,
borderColor: AppColor.primaryMain,
icon: controller.imagePaths.icAddIdentity,
onTapAction: controller.tapAddCondition,
),
),
Padding(
padding: const EdgeInsetsDirectional.only(
top: 24,
bottom: 8,
),
child: Text(
appLocalizations.actionsToPerform,
style: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
), ),
const SizedBox(height: 8), ),
_buildListRuleFilterConditionList( ),
context, _buildListRuleFilterActionList(context),
RuleFilterConditionScreenType.desktop, Obx(() {
), if (controller.isShowAddAction.value == true) {
Container( return Container(
constraints: const BoxConstraints(minWidth: 161), constraints: const BoxConstraints(minWidth: 161),
height: 36, height: 36,
margin: const EdgeInsetsDirectional.only(top: 12), margin: const EdgeInsetsDirectional.only(top: 4),
child: ConfirmDialogButton( child: ConfirmDialogButton(
label: AppLocalizations.of(context).addACondition, label: AppLocalizations.of(context).addAnAction,
backgroundColor: Colors.white, backgroundColor: Colors.white,
textColor: AppColor.primaryMain, textColor: AppColor.primaryMain,
borderColor: AppColor.primaryMain, borderColor: AppColor.primaryMain,
icon: controller.imagePaths.icAddIdentity, icon: controller.imagePaths.icAddIdentity,
onTapAction: controller.tapAddCondition, onTapAction: controller.tapAddAction,
), ),
), );
Padding( } else {
padding: const EdgeInsetsDirectional.only( return const SizedBox.shrink();
top: 24, }
bottom: 8, }),
), ],
child: Text(
appLocalizations.actionsToPerform,
style: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
),
_buildListRuleFilterActionList(context),
Obx(() {
if (controller.isShowAddAction.value == true) {
return Container(
constraints: const BoxConstraints(minWidth: 161),
height: 36,
margin: const EdgeInsetsDirectional.only(top: 4),
child: ConfirmDialogButton(
label: AppLocalizations.of(context).addAnAction,
backgroundColor: Colors.white,
textColor: AppColor.primaryMain,
borderColor: AppColor.primaryMain,
icon: controller.imagePaths.icAddIdentity,
onTapAction: controller.tapAddAction,
),
);
} else {
return const SizedBox.shrink();
}
}),
],
),
),
), ),
), ),
RuleFilterListActionWidget( ),
positiveLabel: appLocalizations.createRule,
negativeLabel: appLocalizations.cancel,
padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 32),
onPositiveAction: () => controller.createNewRuleFilter(context),
onNegativeAction: () => controller.closeView(context),
),
],
), ),
DefaultCloseButtonWidget( RuleFilterListActionWidget(
iconClose: controller.imagePaths.icCloseDialog, positiveLabel: appLocalizations.createRule,
onTapActionCallback: () => controller.closeView(context), negativeLabel: appLocalizations.cancel,
padding: EdgeInsets.symmetric(
vertical: 25,
horizontal: isMobile ? 16 : 32,
),
onPositiveAction: () => controller.createNewRuleFilter(context),
onNegativeAction: () => controller.closeView(context),
), ),
], ],
); );
}
Widget _buildRulesFilterFormOnMobile(BuildContext context) { if (isMobile) {
return Stack( return formWidget;
} else {
return Stack(
children: [ children: [
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ formWidget,
Container( DefaultCloseButtonWidget(
padding: const EdgeInsets.only(top: 16), iconClose: controller.imagePaths.icCloseDialog,
alignment: Alignment.center, onTapActionCallback: () => controller.closeView(context),
child: Obx(() => Text( ),
controller.actionType.value.getTitle(AppLocalizations.of(context)), ],
style: ThemeUtils.defaultTextStyleInterFont.copyWith( );
fontWeight: FontWeight.bold, }
fontSize: 20,
color: Colors.black)))),
Expanded(child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Obx(() => RulesFilterInputField(
hintText: AppLocalizations.of(context).rulesNameHintTextInput,
errorText: controller.errorRuleName.value,
editingController: controller.inputRuleNameController,
focusNode: controller.inputRuleNameFocusNode,
onChangeAction: (value) => controller.updateRuleName(context, value),)),
const Padding(
padding: EdgeInsets.symmetric(vertical: 12),
child: Divider(),
),
Obx(() => RuleFilterTitle(
conditionCombinerType: controller.conditionCombinerType.value,
responsiveUtils: controller.responsiveUtils,
ruleFilterConditionScreenType: RuleFilterConditionScreenType.mobile,
tapActionCallback: (_) {
controller.selectRuleConditionCombinerAction(
context,
controller.conditionCombinerType.value
?? ConditionCombiner.AND,
);
},
)),
const SizedBox(height: 24),
_buildListRuleFilterConditionList(context, RuleFilterConditionScreenType.mobile),
Container(
padding: const EdgeInsets.only(top: 12),
child: InkWell(
onTap: controller.tapAddCondition,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
controller.imagePaths.icAddNewFolder,
fit: BoxFit.fill,
),
const SizedBox(width: 15,),
Text(
AppLocalizations.of(context).addCondition,
maxLines: 1,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: 17,
color: AppColor.primaryColor
)
)
],
),
),
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 12),
child: Divider(),
),
Text(AppLocalizations.of(context).actionTitleRulesFilter,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black)),
const SizedBox(height: 24),
_buildListRuleFilterActionList(context),
Obx(() {
if (controller.isShowAddAction.value == true) {
return Container(
constraints: const BoxConstraints(minWidth: 161),
height: 36,
margin: const EdgeInsetsDirectional.only(top: 4),
child: ConfirmDialogButton(
label: AppLocalizations.of(context).addAnAction,
backgroundColor: Colors.white,
textColor: AppColor.primaryMain,
borderColor: AppColor.primaryMain,
icon: controller.imagePaths.icAddIdentity,
onTapAction: controller.tapAddAction,
),
);
} else {
return const SizedBox.shrink();
}
}),
]
),
),
)),
Container(
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
alignment: Alignment.center,
color: Colors.white,
child: Row(
children: [
Expanded(child: buildTextButton(
AppLocalizations.of(context).cancel,
textStyle: ThemeUtils.defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w500,
fontSize: 17,
color: AppColor.colorTextButton),
backgroundColor: AppColor.emailAddressChipColor,
width: 128,
height: 44,
radius: 10,
onTap: () => controller.closeView(context))),
const SizedBox(width: 12),
Expanded(child: Obx(() => buildTextButton(
controller.actionType.value.getActionName(context),
width: 128,
height: 44,
backgroundColor: AppColor.colorTextButton,
radius: 10,
onTap: () => controller.createNewRuleFilter(context)))),
]
),
)
]),
Positioned(top: 8, right: 8,
child: buildIconWeb(
icon: SvgPicture.asset(
controller.imagePaths.icCircleClose,
fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
onTap: () => controller.closeView(context)))
]
);
} }
Widget _buildListRuleFilterConditionList( Widget _buildListRuleFilterConditionList({
BuildContext context, required BuildContext context,
RuleFilterConditionScreenType ruleFilterConditionScreenType, required bool isMobile,
) { }) {
return Obx(() { return Obx(() {
return ListView.builder( return ListView.builder(
shrinkWrap: true, shrinkWrap: true,
primary: false,
itemCount: controller.listRuleCondition.length, itemCount: controller.listRuleCondition.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final conditionItem = final conditionItem =
controller.listRuleConditionValueArguments[index]; controller.listRuleConditionValueArguments[index];
return RuleFilterConditionWidget( return RuleFilterConditionWidget(
key: ValueKey(conditionItem.focusNode), key: ValueKey(conditionItem.focusNode),
ruleFilterConditionScreenType: ruleFilterConditionScreenType, isMobile: isMobile,
ruleCondition: controller.listRuleCondition[index], ruleCondition: controller.listRuleCondition[index],
imagePaths: controller.imagePaths, imagePaths: controller.imagePaths,
conditionValueErrorText: conditionItem.errorText, conditionValueErrorText: conditionItem.errorText,
@@ -457,7 +303,7 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
context, context,
value, value,
controller.listRuleCondition[index].field, controller.listRuleCondition[index].field,
ruleFilterConditionScreenType, isMobile,
index, index,
), ),
tapRuleConditionComparatorCallback: (value) => tapRuleConditionComparatorCallback: (value) =>
@@ -465,7 +311,7 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
context, context,
value, value,
controller.listRuleCondition[index].comparator, controller.listRuleCondition[index].comparator,
ruleFilterConditionScreenType, isMobile,
index, index,
), ),
conditionValueOnChangeAction: (value) => conditionValueOnChangeAction: (value) =>
@@ -482,6 +328,7 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
return Obx(() { return Obx(() {
return ListView.builder( return ListView.builder(
shrinkWrap: true, shrinkWrap: true,
primary: false,
itemCount: controller.listEmailRuleFilterActionSelected.length, itemCount: controller.listEmailRuleFilterActionSelected.length,
padding: const EdgeInsetsDirectional.only(bottom: 8), padding: const EdgeInsetsDirectional.only(bottom: 8),
itemBuilder: (context, index) { itemBuilder: (context, index) {
@@ -534,4 +381,14 @@ class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
); );
}); });
} }
EdgeInsetsGeometry _getPadding(BuildContext context) {
if (controller.responsiveUtils.isPortraitMobile(context)) {
return const EdgeInsetsDirectional.only(start: 8, end: 16);
} else if (controller.responsiveUtils.isLandscapeMobile(context)) {
return const EdgeInsetsDirectional.symmetric(horizontal: 24);
} else {
return const EdgeInsetsDirectional.symmetric(horizontal: 32);
}
}
} }
@@ -1,7 +0,0 @@
class RuleFilterActionStyles {
static const double extentRatio = 0.1;
static const double removeButtonRadius = 110.0;
static const double mainPadding = 12.0;
static const double mainBorderRadius = 12.0;
static const double itemDistance = 12.0;
}
@@ -1,67 +0,0 @@
import 'package:core/core.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
class RuleActionSheetActionTileBuilder
extends CupertinoActionSheetNoIconBuilder<EmailRuleFilterAction> {
final EmailRuleFilterAction ruleAction;
final EmailRuleFilterAction? ruleActionCurrent;
final SvgPicture? actionSelected;
final Color? bgColor;
final EdgeInsets? iconLeftPadding;
final EdgeInsets? iconRightPadding;
RuleActionSheetActionTileBuilder(
String actionName,
this.ruleActionCurrent,
this.ruleAction,
{
Key? key,
this.actionSelected,
this.bgColor,
this.iconLeftPadding,
this.iconRightPadding,
}
) : super(actionName, key: key);
@override
Widget build() {
return Container(
color: bgColor ?? Colors.white,
child: MouseRegion(
cursor: PlatformInfo.isWeb
? WidgetStateMouseCursor.clickable
: MouseCursor.defer,
child: CupertinoActionSheetAction(
key: key,
child: Stack(
children: [
Center(
child: Text(actionName,
textAlign: TextAlign.center,
style: actionTextStyle()),
),
if (ruleActionCurrent == ruleAction && actionSelected != null)
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: iconRightPadding ??
const EdgeInsets.only(right: 12),
child: actionSelected!),
),
],
),
onPressed: () {
if (onCupertinoActionSheetActionClick != null) {
onCupertinoActionSheetActionClick!(ruleAction);
}
},
),
),
);
}
}
@@ -1,68 +0,0 @@
import 'package:core/core.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_svg/svg.dart';
import 'package:rule_filter/rule_filter/rule_condition_group.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/styles/rule_condition_combiner_bottom_sheet_styles.dart';
class RuleConditionCombinerSheetActionTileBuilder
extends CupertinoActionSheetNoIconBuilder<ConditionCombiner> {
final ConditionCombiner combiner;
final ConditionCombiner? combinerCurrent;
final SvgPicture? actionSelected;
final Color? bgColor;
final EdgeInsets? iconLeftPadding;
final EdgeInsets? iconRightPadding;
RuleConditionCombinerSheetActionTileBuilder(
String actionName,
this.combiner,
this.combinerCurrent,
{
Key? key,
this.actionSelected,
this.bgColor,
this.iconLeftPadding,
this.iconRightPadding,
}
) : super(actionName, key: key);
@override
Widget build() {
return Container(
color: bgColor ?? RuleConditionCombinerBottomSheetStyles.defaultBgColor,
child: MouseRegion(
cursor: PlatformInfo.isWeb
? WidgetStateMouseCursor.clickable
: MouseCursor.defer,
child: CupertinoActionSheetAction(
key: key,
child: Stack(
children: [
Center(
child: Text(
actionName,
textAlign: TextAlign.center,
style: actionTextStyle()
),
),
if (combinerCurrent == combiner && actionSelected != null)
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: iconRightPadding ?? const EdgeInsets.only(right: RuleConditionCombinerBottomSheetStyles.defaultIconRightPadding),
child: actionSelected!
),
),
],
),
onPressed: () {
if (onCupertinoActionSheetActionClick != null) {
onCupertinoActionSheetActionClick!(combiner);
}
},
),
),
);
}
}
@@ -1,67 +0,0 @@
import 'package:core/core.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition;
class RuleConditionComparatorSheetActionTileBuilder
extends CupertinoActionSheetNoIconBuilder<rule_condition.Comparator> {
final rule_condition.Comparator comparator;
final rule_condition.Comparator? comparatorCurrent;
final SvgPicture? actionSelected;
final Color? bgColor;
final EdgeInsets? iconLeftPadding;
final EdgeInsets? iconRightPadding;
RuleConditionComparatorSheetActionTileBuilder(
String actionName,
this.comparatorCurrent,
this.comparator,
{
Key? key,
this.actionSelected,
this.bgColor,
this.iconLeftPadding,
this.iconRightPadding,
}
) : super(actionName, key: key);
@override
Widget build() {
return Container(
color: bgColor ?? Colors.white,
child: MouseRegion(
cursor: PlatformInfo.isWeb
? WidgetStateMouseCursor.clickable
: MouseCursor.defer,
child: CupertinoActionSheetAction(
key: key,
child: Stack(
children: [
Center(
child: Text(actionName,
textAlign: TextAlign.center,
style: actionTextStyle()),
),
if (comparatorCurrent == comparator && actionSelected != null)
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: iconRightPadding ??
const EdgeInsets.only(right: 12),
child: actionSelected!),
),
],
),
onPressed: () {
if (onCupertinoActionSheetActionClick != null) {
onCupertinoActionSheetActionClick!(comparator);
}
},
),
),
);
}
}
@@ -1,67 +0,0 @@
import 'package:core/core.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition;
class RuleConditionFieldSheetActionTileBuilder
extends CupertinoActionSheetNoIconBuilder<rule_condition.Field> {
final rule_condition.Field field;
final rule_condition.Field? fieldCurrent;
final SvgPicture? actionSelected;
final Color? bgColor;
final EdgeInsets? iconLeftPadding;
final EdgeInsets? iconRightPadding;
RuleConditionFieldSheetActionTileBuilder(
String actionName,
this.fieldCurrent,
this.field,
{
Key? key,
this.actionSelected,
this.bgColor,
this.iconLeftPadding,
this.iconRightPadding,
}
) : super(actionName, key: key);
@override
Widget build() {
return Container(
color: bgColor ?? Colors.white,
child: MouseRegion(
cursor: PlatformInfo.isWeb
? WidgetStateMouseCursor.clickable
: MouseCursor.defer,
child: CupertinoActionSheetAction(
key: key,
child: Stack(
children: [
Center(
child: Text(actionName,
textAlign: TextAlign.center,
style: actionTextStyle()),
),
if (fieldCurrent == field && actionSelected != null)
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: iconRightPadding ??
const EdgeInsets.only(right: 12),
child: actionSelected!),
),
],
),
onPressed: () {
if (onCupertinoActionSheetActionClick != null) {
onCupertinoActionSheetActionClick!(field);
}
},
),
),
);
}
}
@@ -4,10 +4,11 @@ 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/rules_filter_input_field_builder.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 {
final ImagePaths imagePaths;
final EmailRuleFilterAction? actionType; final EmailRuleFilterAction? actionType;
final PresentationMailbox? mailboxSelected; final PresentationMailbox? mailboxSelected;
final String? errorValue; final String? errorValue;
@@ -18,6 +19,7 @@ class RuleFilterActionDetailed extends StatelessWidget {
const RuleFilterActionDetailed({ const RuleFilterActionDetailed({
Key? key, Key? key,
required this.imagePaths,
this.actionType, this.actionType,
this.mailboxSelected, this.mailboxSelected,
this.errorValue, this.errorValue,
@@ -34,8 +36,9 @@ class RuleFilterActionDetailed extends StatelessWidget {
case EmailRuleFilterAction.moveMessage: case EmailRuleFilterAction.moveMessage:
return RuleFilterButtonField<PresentationMailbox>( return RuleFilterButtonField<PresentationMailbox>(
value: mailboxSelected, value: mailboxSelected,
imagePaths: imagePaths,
borderColor: borderColor, borderColor: borderColor,
tapActionCallback: (value) { onTapActionCallback: (value) {
tapActionDetailedCallback!(); tapActionDetailedCallback!();
}, },
); );
@@ -7,8 +7,8 @@ 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/features/rules_filter_creator/presentation/widgets/rules_filter_input_field_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class RuleFilterActionRow extends StatelessWidget { class RuleFilterActionRow extends StatelessWidget {
@@ -81,10 +81,11 @@ class RuleFilterActionRow extends StatelessWidget {
Expanded( Expanded(
child: RuleFilterButtonField<PresentationMailbox>( child: RuleFilterButtonField<PresentationMailbox>(
value: mailboxSelected, value: mailboxSelected,
imagePaths: imagePaths,
borderColor: errorValue?.isNotEmpty == true borderColor: errorValue?.isNotEmpty == true
? AppColor.redFF3347 ? AppColor.redFF3347
: AppColor.m3Neutral90, : AppColor.m3Neutral90,
tapActionCallback: (_) => tapActionDetailedCallback?.call(), onTapActionCallback: (_) => tapActionDetailedCallback?.call(),
), ),
), ),
] ]
@@ -102,7 +103,7 @@ class RuleFilterActionRow extends StatelessWidget {
RuleFilterDeleteButtonWidget( RuleFilterDeleteButtonWidget(
imagePaths: imagePaths, imagePaths: imagePaths,
onDeleteRuleConditionAction: onDeleteRuleConditionAction, onDeleteRuleConditionAction: onDeleteRuleConditionAction,
) ),
], ],
); );
} }
@@ -2,13 +2,13 @@ import 'package:core/core.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/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/styles/rule_filter_action_styles.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/rules_filter_input_field_builder.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 EmailRuleFilterAction? actionSelected; final EmailRuleFilterAction? actionSelected;
final Function()? tapActionCallback; final Function()? tapActionCallback;
final PresentationMailbox? mailboxSelected; final PresentationMailbox? mailboxSelected;
@@ -20,6 +20,7 @@ class RuleFilterActionRowMobile extends StatelessWidget {
const RuleFilterActionRowMobile({ const RuleFilterActionRowMobile({
Key? key, Key? key,
required this.imagePaths,
this.actionSelected, this.actionSelected,
this.tapActionCallback, this.tapActionCallback,
this.mailboxSelected, this.mailboxSelected,
@@ -37,7 +38,8 @@ class RuleFilterActionRowMobile extends StatelessWidget {
children: [ children: [
RuleFilterButtonField<EmailRuleFilterAction>( RuleFilterButtonField<EmailRuleFilterAction>(
value: actionSelected, value: actionSelected,
tapActionCallback: (value) { imagePaths: imagePaths,
onTapActionCallback: (value) {
tapActionCallback!(); tapActionCallback!();
}, },
hintText: AppLocalizations.of(context).selectAction, hintText: AppLocalizations.of(context).selectAction,
@@ -45,7 +47,7 @@ class RuleFilterActionRowMobile extends StatelessWidget {
actionSelected == EmailRuleFilterAction.moveMessage actionSelected == EmailRuleFilterAction.moveMessage
? Container( ? Container(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(vertical: RuleFilterActionStyles.mainPadding), padding: const EdgeInsets.symmetric(vertical: 12),
child: Text( child: Text(
AppLocalizations.of(context).toFolder, AppLocalizations.of(context).toFolder,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@@ -58,9 +60,10 @@ class RuleFilterActionRowMobile extends StatelessWidget {
), ),
) )
: SizedBox( : SizedBox(
height: actionSelected == EmailRuleFilterAction.forwardTo ? RuleFilterActionStyles.itemDistance : 0, height: actionSelected == EmailRuleFilterAction.forwardTo ? 12 : 0,
), ),
RuleFilterActionDetailed( RuleFilterActionDetailed(
imagePaths: imagePaths,
actionType: actionSelected, actionType: actionSelected,
mailboxSelected: mailboxSelected, mailboxSelected: mailboxSelected,
errorValue: errorValue, errorValue: errorValue,
@@ -3,14 +3,12 @@ import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.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:flutter_svg/flutter_svg.dart';
import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:model/mailbox/presentation_mailbox.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/styles/rule_filter_action_styles.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';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rules_filter_input_field_builder.dart';
class RuleFilterActionWidget extends StatelessWidget { class RuleFilterActionWidget extends StatelessWidget {
final ResponsiveUtils responsiveUtils; final ResponsiveUtils responsiveUtils;
@@ -46,118 +44,90 @@ class RuleFilterActionWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isMobile = responsiveUtils.isMobile(context); final isMobile = responsiveUtils.isMobile(context);
Widget bodyWidget = Container(
padding: const EdgeInsetsDirectional.only(start: 12),
margin: const EdgeInsetsDirectional.only(top: 8),
decoration: const BoxDecoration(
color: AppColor.lightGrayF9FAFB,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
height: 72,
alignment: Alignment.center,
child: isMobile
? RuleFilterActionRowMobile(
actionSelected: actionSelected,
mailboxSelected: mailboxSelected,
errorValue: errorValue,
tapActionDetailedCallback: tapActionDetailedCallback,
forwardEmailEditingController: forwardEmailEditingController,
forwardEmailFocusNode: forwardEmailFocusNode,
onChangeForwardEmail: onChangeForwardEmail,
tapActionCallback: onActionChangeMobile,
)
: RuleFilterActionRow(
actionList: EmailRuleFilterAction.values,
actionSelected: actionSelected,
onActionChanged: onActionChanged,
mailboxSelected: mailboxSelected,
errorValue: errorValue,
tapActionDetailedCallback: tapActionDetailedCallback,
imagePaths: imagePaths,
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
forwardEmailEditingController: forwardEmailEditingController,
forwardEmailFocusNode: forwardEmailFocusNode,
onChangeForwardEmail: onChangeForwardEmail,
),
);
if (!isMobile) { if (!isMobile) {
return bodyWidget; return Container(
} padding: const EdgeInsetsDirectional.only(start: 12),
margin: const EdgeInsetsDirectional.only(top: 8),
return Slidable( decoration: const BoxDecoration(
enabled: responsiveUtils.isMobile(context) ? true : false, color: AppColor.lightGrayF9FAFB,
endActionPane: ActionPane( borderRadius: BorderRadius.all(Radius.circular(10)),
extentRatio: RuleFilterActionStyles.extentRatio, ),
motion: const BehindMotion(), height: 72,
children: [ alignment: Alignment.center,
CustomSlidableAction( child: RuleFilterActionRow(
padding: const EdgeInsets.only(right: RuleFilterActionStyles.mainPadding), actionList: EmailRuleFilterAction.values,
borderRadius: const BorderRadius.only( actionSelected: actionSelected,
topRight: Radius.circular(RuleFilterActionStyles.mainBorderRadius), onActionChanged: onActionChanged,
bottomRight: Radius.circular(RuleFilterActionStyles.mainBorderRadius), mailboxSelected: mailboxSelected,
), errorValue: errorValue,
onPressed: (_) => onDeleteRuleConditionAction(), tapActionDetailedCallback: tapActionDetailedCallback,
backgroundColor: AppColor.colorBackgroundFieldConditionRulesFilter, imagePaths: imagePaths,
child: CircleAvatar( onDeleteRuleConditionAction: onDeleteRuleConditionAction,
backgroundColor: AppColor.colorRemoveRuleFilterConditionButton, forwardEmailEditingController: forwardEmailEditingController,
radius: RuleFilterActionStyles.removeButtonRadius, forwardEmailFocusNode: forwardEmailFocusNode,
child: SvgPicture.asset( onChangeForwardEmail: onChangeForwardEmail,
imagePaths.icMinimize, ),
fit: BoxFit.fill, );
colorFilter: AppColor.colorDeletePermanentlyButton.asFilter(), } else {
), return Padding(
), padding: const EdgeInsetsDirectional.only(top: 8),
) child: Slidable(
], endActionPane: ActionPane(
), extentRatio: 0.15,
child: Builder( motion: const BehindMotion(),
builder: (context) { children: [
SlidableController? slideController = Slidable.of(context); CustomSlidableAction(
return ValueListenableBuilder<int>( padding: const EdgeInsets.only(right: 12),
valueListenable: slideController?.direction ?? ValueNotifier<int>(0), borderRadius: const BorderRadius.only(
builder: (context, value, _) { topRight: Radius.circular(10),
var borderRadius = value != -1 bottomRight: Radius.circular(10),
? BorderRadius.circular(RuleFilterActionStyles.mainBorderRadius)
: const BorderRadius.only(
bottomLeft: Radius.circular(RuleFilterActionStyles.mainBorderRadius),
topLeft: Radius.circular(RuleFilterActionStyles.mainBorderRadius),
);
return Container(
padding: const EdgeInsets.all(RuleFilterActionStyles.mainPadding),
decoration: BoxDecoration(
color: AppColor.colorBackgroundFieldConditionRulesFilter,
borderRadius: borderRadius,
), ),
child: responsiveUtils.isMobile(context) onPressed: (_) => onDeleteRuleConditionAction(),
? RuleFilterActionRowMobile( backgroundColor: AppColor.lightGrayF9FAFB,
actionSelected: actionSelected, child: RuleFilterDeleteButtonWidget(
mailboxSelected: mailboxSelected, imagePaths: imagePaths,
errorValue: errorValue, onDeleteRuleConditionAction: onDeleteRuleConditionAction,
tapActionDetailedCallback: tapActionDetailedCallback, ),
forwardEmailEditingController: forwardEmailEditingController, )
forwardEmailFocusNode: forwardEmailFocusNode, ],
onChangeForwardEmail: onChangeForwardEmail, ),
tapActionCallback: onActionChangeMobile, child: Builder(
) builder: (context) {
: RuleFilterActionRow( SlidableController? slideController = Slidable.of(context);
actionList: EmailRuleFilterAction.values, return ValueListenableBuilder<int>(
actionSelected: actionSelected, valueListenable: slideController?.direction ?? ValueNotifier<int>(0),
onActionChanged: onActionChanged, builder: (context, value, _) {
mailboxSelected: mailboxSelected, final borderRadius = value != -1
errorValue: errorValue, ? BorderRadius.circular(10)
tapActionDetailedCallback: tapActionDetailedCallback, : const BorderRadius.only(
imagePaths: imagePaths, bottomLeft: Radius.circular(10),
onDeleteRuleConditionAction: onDeleteRuleConditionAction, topLeft: Radius.circular(10),
forwardEmailEditingController: forwardEmailEditingController, );
forwardEmailFocusNode: forwardEmailFocusNode, return Container(
onChangeForwardEmail: onChangeForwardEmail, padding: const EdgeInsetsDirectional.all(8),
) decoration: BoxDecoration(
); color: AppColor.lightGrayF9FAFB,
}, borderRadius: borderRadius,
); ),
} alignment: Alignment.center,
), child: RuleFilterActionRowMobile(
); imagePaths: imagePaths,
actionSelected: actionSelected,
mailboxSelected: mailboxSelected,
errorValue: errorValue,
tapActionDetailedCallback: tapActionDetailedCallback,
forwardEmailEditingController: forwardEmailEditingController,
forwardEmailFocusNode: forwardEmailFocusNode,
onChangeForwardEmail: onChangeForwardEmail,
tapActionCallback: onActionChangeMobile,
),
);
},
);
}
),
),
);
}
} }
} }
@@ -1,11 +1,9 @@
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/style_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart'; import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition; import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition;
import 'package:rule_filter/rule_filter/rule_condition_group.dart'; import 'package:rule_filter/rule_filter/rule_condition_group.dart';
@@ -14,49 +12,57 @@ import 'package:tmail_ui_user/features/rules_filter_creator/presentation/extensi
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/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnTapActionCallback<T> = Function(T? value); typedef OnRuleTapActionCallback<T> = Function(T? value);
class RuleFilterButtonField<T> extends StatelessWidget { class RuleFilterButtonField<T> extends StatelessWidget {
final T? value; final T? value;
final OnTapActionCallback? tapActionCallback; final OnRuleTapActionCallback onTapActionCallback;
final ImagePaths imagePaths;
final Color? borderColor; final Color? borderColor;
final String? hintText; final String? hintText;
const RuleFilterButtonField({ const RuleFilterButtonField({
super.key, super.key,
this.value, required this.value,
this.tapActionCallback, required this.imagePaths,
required this.onTapActionCallback,
this.borderColor, this.borderColor,
this.hintText, this.hintText,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final imagePaths = Get.find<ImagePaths>(); return Material(
final Color textColor = value != null ? Colors.black : AppColor.textFieldHintColor; type: MaterialType.transparency,
child: InkWell(
return InkWell( onTap: () => onTapActionCallback(value),
onTap: () => tapActionCallback?.call(value), borderRadius: const BorderRadius.all(Radius.circular(10)),
child: Container( child: Container(
height: 44, height: 40,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10), borderRadius: const BorderRadius.all(Radius.circular(10)),
border: Border.all( border: Border.all(
color: borderColor ?? AppColor.colorInputBorderCreateMailbox, color: borderColor ?? AppColor.m3Neutral90,
width: 1), width: 1,
color: Colors.white), ),
padding: const EdgeInsets.only(left: 12, right: 10), color: Colors.white
child: Row(children: [ ),
Expanded(child: Text( padding: const EdgeInsetsDirectional.only(start: 12, end: 10),
_getName(context, value), child: Row(children: [
style: ThemeUtils.textStyleBodyBody3(color: textColor), Expanded(child: Text(
maxLines: 1, _getName(context, value),
softWrap: CommonTextStyle.defaultSoftWrap, style: ThemeUtils.textStyleBodyBody3(
overflow: CommonTextStyle.defaultTextOverFlow, color: value != null
)), ? Colors.black
SvgPicture.asset(imagePaths.icDropDown) : AppColor.textFieldHintColor,
]), ),
maxLines: 1,
overflow: TextOverflow.ellipsis,
)),
SvgPicture.asset(imagePaths.icDropDown)
]),
),
), ),
); );
} }
@@ -1,25 +1,23 @@
import 'package:core/core.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/keyboard_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart'; import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition; import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition;
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/model/rule_filter_condition_type.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/features/rules_filter_creator/presentation/widgets/rules_filter_input_field_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class RuleFilterConditionRow extends StatelessWidget { class RuleFilterConditionRow extends StatelessWidget {
final RuleFilterConditionScreenType? ruleFilterConditionScreenType; final bool isMobile;
final RuleCondition ruleCondition; final RuleCondition ruleCondition;
final ImagePaths imagePaths; final ImagePaths imagePaths;
final OnDeleteRuleConditionAction onDeleteRuleConditionAction; final OnDeleteRuleConditionAction onDeleteRuleConditionAction;
final Function(Field?)? tapRuleConditionFieldCallback; final OnRuleTapActionCallback tapRuleConditionFieldCallback;
final Function(Comparator?)? tapRuleConditionComparatorCallback; final OnRuleTapActionCallback tapRuleConditionComparatorCallback;
final String? conditionValueErrorText; final String? conditionValueErrorText;
final TextEditingController textEditingController; final TextEditingController textEditingController;
final FocusNode? conditionValueFocusNode; final FocusNode? conditionValueFocusNode;
@@ -27,13 +25,13 @@ class RuleFilterConditionRow extends StatelessWidget {
const RuleFilterConditionRow({ const RuleFilterConditionRow({
Key? key, Key? key,
required this.ruleFilterConditionScreenType, required this.isMobile,
required this.ruleCondition, required this.ruleCondition,
required this.imagePaths, required this.imagePaths,
required this.textEditingController, required this.textEditingController,
required this.onDeleteRuleConditionAction, required this.onDeleteRuleConditionAction,
this.tapRuleConditionFieldCallback, required this.tapRuleConditionFieldCallback,
this.tapRuleConditionComparatorCallback, required this.tapRuleConditionComparatorCallback,
this.conditionValueErrorText, this.conditionValueErrorText,
this.conditionValueFocusNode, this.conditionValueFocusNode,
this.conditionValueOnChangeAction, this.conditionValueOnChangeAction,
@@ -41,99 +39,88 @@ class RuleFilterConditionRow extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
switch (ruleFilterConditionScreenType) { if (isMobile) {
case RuleFilterConditionScreenType.mobile: return Column(
return Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
children: [ RuleFilterButtonField<rule_condition.Field>(
RuleFilterButtonField<rule_condition.Field>( value: ruleCondition.field,
value: ruleCondition.field, imagePaths: imagePaths,
tapActionCallback: (value) { onTapActionCallback: tapRuleConditionFieldCallback,
KeyboardUtils.hideKeyboard(context); ),
tapRuleConditionFieldCallback!(ruleCondition.field); Padding(
}, padding: const EdgeInsets.symmetric(vertical: 8),
child: RuleFilterButtonField<rule_condition.Comparator>(
value: ruleCondition.comparator,
imagePaths: imagePaths,
onTapActionCallback: tapRuleConditionComparatorCallback,
), ),
Padding( ),
padding: const EdgeInsets.symmetric(vertical: 12), DefaultInputFieldWidget(
child: RuleFilterButtonField<rule_condition.Comparator>( hintText: AppLocalizations.of(context).conditionValueHintTextInput,
value: ruleCondition.comparator, errorText: conditionValueErrorText,
tapActionCallback: (value) { focusNode: conditionValueFocusNode,
KeyboardUtils.hideKeyboard(context); inputColor: Colors.black,
tapRuleConditionComparatorCallback!(ruleCondition.comparator); onTextChange: conditionValueOnChangeAction,
}, textEditingController: textEditingController,
) ),
],
);
} else {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(width: 12),
Expanded(
child: DropDownButtonWidget<rule_condition.Field>(
items: rule_condition.Field.values,
itemSelected: ruleCondition.field,
dropdownMaxHeight: 250,
heightItem: 40,
labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black,
),
hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400,
),
onChanged: tapRuleConditionFieldCallback,
supportSelectionIcon: true,
), ),
RulesFilterInputField( ),
hintText: AppLocalizations.of(context).conditionValueHintTextInput, const SizedBox(width: 8),
Expanded(
child: DropDownButtonWidget<rule_condition.Comparator>(
items: rule_condition.Comparator.values,
itemSelected: ruleCondition.comparator,
heightItem: 40,
labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black,
),
hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400,
),
onChanged: tapRuleConditionComparatorCallback,
supportSelectionIcon: true,
)),
const SizedBox(width: 8),
Expanded(
child: DefaultInputFieldWidget(
hintText:
AppLocalizations.of(context).conditionValueHintTextInput,
errorText: conditionValueErrorText, errorText: conditionValueErrorText,
focusNode: conditionValueFocusNode, focusNode: conditionValueFocusNode,
onChangeAction: conditionValueOnChangeAction, inputColor: Colors.black,
editingController: textEditingController, onTextChange: conditionValueOnChangeAction,
textEditingController: textEditingController,
), ),
], ),
); RuleFilterDeleteButtonWidget(
case RuleFilterConditionScreenType.tablet: imagePaths: imagePaths,
case RuleFilterConditionScreenType.desktop: margin: const EdgeInsetsDirectional.only(top: 2),
return Row( onDeleteRuleConditionAction: onDeleteRuleConditionAction,
crossAxisAlignment: CrossAxisAlignment.start, ),
children: [ ],
const SizedBox(width: 12), );
Expanded(
child: DropDownButtonWidget<rule_condition.Field>(
items: rule_condition.Field.values,
itemSelected: ruleCondition.field,
dropdownMaxHeight: 250,
heightItem: 40,
labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black,
),
hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400,
),
onChanged: (newField) => {
tapRuleConditionFieldCallback!(newField)
},
supportSelectionIcon: true,
)
),
const SizedBox(width: 8),
Expanded(
child: DropDownButtonWidget<rule_condition.Comparator>(
items: rule_condition.Comparator.values,
itemSelected: ruleCondition.comparator,
heightItem: 40,
labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black,
),
hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400,
),
onChanged: (newComparator) => {
tapRuleConditionComparatorCallback!(newComparator)
},
supportSelectionIcon: true,
)
),
const SizedBox(width: 8),
Expanded(
child: DefaultInputFieldWidget(
hintText: AppLocalizations.of(context).conditionValueHintTextInput,
errorText: conditionValueErrorText,
focusNode: conditionValueFocusNode,
inputColor: Colors.black,
onTextChange: conditionValueOnChangeAction,
textEditingController: textEditingController,
),
),
RuleFilterDeleteButtonWidget(
imagePaths: imagePaths,
margin: const EdgeInsetsDirectional.only(top: 2),
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
),
],
);
default:
return const SizedBox.shrink();
} }
} }
} }
@@ -1,20 +1,20 @@
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:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rule_filter_condition_type.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/rules_filter_creator/presentation/widgets/rule_filter_delete_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_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/rules_filter_input_field_builder.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_filter_delete_button_widget.dart';
import 'package:core/presentation/resources/image_paths.dart';
typedef OnChangeFilterInputAction = Function(String? value);
class RuleFilterConditionWidget extends StatelessWidget { class RuleFilterConditionWidget extends StatelessWidget {
final RuleFilterConditionScreenType? ruleFilterConditionScreenType; final bool isMobile;
final RuleCondition ruleCondition; final RuleCondition ruleCondition;
final TextEditingController textEditingController; final TextEditingController textEditingController;
final Function(Field?)? tapRuleConditionFieldCallback; final OnRuleTapActionCallback tapRuleConditionFieldCallback;
final Function(Comparator?)? tapRuleConditionComparatorCallback; final OnRuleTapActionCallback tapRuleConditionComparatorCallback;
final String? conditionValueErrorText; final String? conditionValueErrorText;
final FocusNode? conditionValueFocusNode; final FocusNode? conditionValueFocusNode;
final OnChangeFilterInputAction? conditionValueOnChangeAction; final OnChangeFilterInputAction? conditionValueOnChangeAction;
@@ -23,13 +23,13 @@ class RuleFilterConditionWidget extends StatelessWidget {
const RuleFilterConditionWidget({ const RuleFilterConditionWidget({
super.key, super.key,
this.ruleFilterConditionScreenType, required this.isMobile,
required this.ruleCondition, required this.ruleCondition,
required this.imagePaths, required this.imagePaths,
required this.textEditingController, required this.textEditingController,
required this.onDeleteRuleConditionAction, required this.onDeleteRuleConditionAction,
this.tapRuleConditionFieldCallback, required this.tapRuleConditionFieldCallback,
this.tapRuleConditionComparatorCallback, required this.tapRuleConditionComparatorCallback,
this.conditionValueErrorText, this.conditionValueErrorText,
this.conditionValueFocusNode, this.conditionValueFocusNode,
this.conditionValueOnChangeAction, this.conditionValueOnChangeAction,
@@ -37,59 +37,89 @@ class RuleFilterConditionWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget bodyWidget = Container( if (isMobile) {
padding: const EdgeInsetsDirectional.symmetric(vertical: 12), return Padding(
margin: const EdgeInsetsDirectional.only(top: 8), padding: const EdgeInsetsDirectional.only(top: 8),
decoration: const BoxDecoration( child: Slidable(
color: AppColor.lightGrayF9FAFB, endActionPane: ActionPane(
borderRadius: BorderRadius.all(Radius.circular(10)), extentRatio: 0.15,
), motion: const BehindMotion(),
alignment: Alignment.center, children: [
child: RuleFilterConditionRow( CustomSlidableAction(
ruleFilterConditionScreenType: ruleFilterConditionScreenType, padding: const EdgeInsets.only(right: 12),
ruleCondition: ruleCondition, borderRadius: const BorderRadius.only(
tapRuleConditionFieldCallback: tapRuleConditionFieldCallback, topRight: Radius.circular(10),
tapRuleConditionComparatorCallback: tapRuleConditionComparatorCallback, bottomRight: Radius.circular(10),
conditionValueErrorText: conditionValueErrorText, ),
textEditingController: textEditingController, onPressed: (_) => onDeleteRuleConditionAction(),
conditionValueFocusNode: conditionValueFocusNode, backgroundColor: AppColor.lightGrayF9FAFB,
conditionValueOnChangeAction: conditionValueOnChangeAction, child: RuleFilterDeleteButtonWidget(
onDeleteRuleConditionAction: onDeleteRuleConditionAction, imagePaths: imagePaths,
imagePaths: imagePaths, onDeleteRuleConditionAction: onDeleteRuleConditionAction,
), ),
);
if (ruleFilterConditionScreenType != RuleFilterConditionScreenType.mobile) {
return bodyWidget;
}
return Slidable(
enabled: ruleFilterConditionScreenType == RuleFilterConditionScreenType.mobile ? true : false,
endActionPane: ActionPane(
extentRatio: 0.1,
motion: const BehindMotion(),
children: [
CustomSlidableAction(
padding: const EdgeInsets.only(right: 12),
borderRadius: const BorderRadius.only(topRight: Radius.circular(12), bottomRight: Radius.circular(12)),
onPressed: (_) => onDeleteRuleConditionAction(),
backgroundColor: AppColor.colorBackgroundFieldConditionRulesFilter,
child: CircleAvatar(
backgroundColor: AppColor.colorRemoveRuleFilterConditionButton,
radius: 110,
child: SvgPicture.asset(
imagePaths.icMinimize,
fit: BoxFit.fill,
colorFilter: AppColor.colorDeletePermanentlyButton.asFilter(),
), ),
) ],
) ),
] child: Builder(
), builder: (context) {
child: ValueListenableBuilder<int>( SlidableController? slideController = Slidable.of(context);
valueListenable: Slidable.of(context)?.direction ?? ValueNotifier<int>(0), return ValueListenableBuilder<int>(
builder: (_, __, ___) => bodyWidget, valueListenable: slideController?.direction ?? ValueNotifier<int>(0),
), builder: (context, value, _) {
); final borderRadius = value != -1
? BorderRadius.circular(10)
: const BorderRadius.only(
bottomLeft: Radius.circular(10),
topLeft: Radius.circular(10),
);
return Container(
padding: const EdgeInsetsDirectional.all(8),
decoration: BoxDecoration(
color: AppColor.lightGrayF9FAFB,
borderRadius: borderRadius,
),
alignment: Alignment.center,
child: RuleFilterConditionRow(
isMobile: isMobile,
ruleCondition: ruleCondition,
tapRuleConditionFieldCallback: tapRuleConditionFieldCallback,
tapRuleConditionComparatorCallback: tapRuleConditionComparatorCallback,
conditionValueErrorText: conditionValueErrorText,
textEditingController: textEditingController,
conditionValueFocusNode: conditionValueFocusNode,
conditionValueOnChangeAction: conditionValueOnChangeAction,
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
imagePaths: imagePaths,
),
);
}
);
}
),
),
);
} else {
return Container(
padding: const EdgeInsetsDirectional.symmetric(vertical: 12),
margin: const EdgeInsetsDirectional.only(top: 8),
decoration: const BoxDecoration(
color: AppColor.lightGrayF9FAFB,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
alignment: Alignment.center,
child: RuleFilterConditionRow(
isMobile: isMobile,
ruleCondition: ruleCondition,
tapRuleConditionFieldCallback: tapRuleConditionFieldCallback,
tapRuleConditionComparatorCallback: tapRuleConditionComparatorCallback,
conditionValueErrorText: conditionValueErrorText,
textEditingController: textEditingController,
conditionValueFocusNode: conditionValueFocusNode,
conditionValueOnChangeAction: conditionValueOnChangeAction,
onDeleteRuleConditionAction: onDeleteRuleConditionAction,
imagePaths: imagePaths,
),
);
}
} }
} }
@@ -1,36 +1,70 @@
import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/utils/keyboard_utils.dart'; import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart'; import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:rule_filter/rule_filter/rule_condition_group.dart'; import 'package:rule_filter/rule_filter/rule_condition_group.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/model/rule_filter_condition_type.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/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
typedef OnTapActionCallback<RuleConditionCombiner> = Function(
ConditionCombiner? value,
);
class RuleFilterTitle extends StatelessWidget { class RuleFilterTitle extends StatelessWidget {
final ImagePaths imagePaths;
final ConditionCombiner? conditionCombinerType; final ConditionCombiner? conditionCombinerType;
final OnTapActionCallback? tapActionCallback; final OnRuleTapActionCallback onTapActionCallback;
final RuleFilterConditionScreenType ruleFilterConditionScreenType; final bool isMobile;
final ResponsiveUtils responsiveUtils;
const RuleFilterTitle({ const RuleFilterTitle({
Key? key, Key? key,
required this.ruleFilterConditionScreenType, required this.imagePaths,
required this.responsiveUtils, required this.isMobile,
this.conditionCombinerType, required this.conditionCombinerType,
this.tapActionCallback, required this.onTapActionCallback,
}) : super(key: key); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final appLocalizations = AppLocalizations.of(context); final appLocalizations = AppLocalizations.of(context);
final isMobile = responsiveUtils.isMobile(context);
if (isMobile) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
Text(
appLocalizations.conditionTitleRulesFilterBeforeCombiner,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
),
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12),
constraints: const BoxConstraints(minWidth: 100),
child: RuleFilterButtonField<ConditionCombiner>(
value: conditionCombinerType,
imagePaths: imagePaths,
onTapActionCallback: onTapActionCallback,
),
),
)
],
),
const SizedBox(height: 8),
Text(
appLocalizations.conditionTitleRulesFilterAfterCombiner,
style: ThemeUtils.textStyleInter400.copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
)
],
);
}
return Wrap( return Wrap(
crossAxisAlignment: WrapCrossAlignment.center, crossAxisAlignment: WrapCrossAlignment.center,
@@ -47,31 +81,19 @@ class RuleFilterTitle extends StatelessWidget {
), ),
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
width: isMobile ? double.infinity : 158, width: 158,
child: ruleFilterConditionScreenType == child: DropDownButtonWidget<ConditionCombiner>(
RuleFilterConditionScreenType.mobile items: ConditionCombiner.values,
? RuleFilterButtonField<ConditionCombiner>( itemSelected: conditionCombinerType,
value: conditionCombinerType, supportSelectionIcon: true,
tapActionCallback: (value) { labelTextStyle: ThemeUtils.textStyleBodyBody3(
KeyboardUtils.hideKeyboard(context); color: Colors.black,
tapActionCallback?.call(value); ),
}, hintTextStyle: ThemeUtils.textStyleBodyBody3(
) color: AppColor.steelGray400,
: DropDownButtonWidget<ConditionCombiner>( ),
items: ConditionCombiner.values, onChanged: onTapActionCallback,
itemSelected: conditionCombinerType, ),
supportSelectionIcon: true,
labelTextStyle: ThemeUtils.textStyleBodyBody3(
color: Colors.black,
),
hintTextStyle: ThemeUtils.textStyleBodyBody3(
color: AppColor.steelGray400,
),
onChanged: (value) {
KeyboardUtils.hideKeyboard(context);
tapActionCallback?.call(value);
},
),
), ),
Text( Text(
appLocalizations.conditionTitleRulesFilterAfterCombiner, appLocalizations.conditionTitleRulesFilterAfterCombiner,
@@ -1,53 +0,0 @@
import 'package:core/core.dart';
import 'package:flutter/material.dart';
class RulesFilterInputDecorationBuilder extends InputDecorationBuilder {
@override
InputDecoration build() {
return InputDecoration(
enabledBorder: enabledBorder ?? const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
width: 1,
color: AppColor.colorInputBorderCreateMailbox)),
focusedBorder: enabledBorder ?? const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
width: 1,
color: AppColor.colorTextButton)),
errorBorder: errorBorder ?? const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
width: 1,
color: AppColor.colorInputBorderErrorVerifyName)),
focusedErrorBorder: errorBorder ?? const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(
width: 1,
color: AppColor.colorInputBorderErrorVerifyName)),
prefixText: prefixText,
labelText: labelText,
floatingLabelBehavior: FloatingLabelBehavior.never,
labelStyle: labelStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(
color: Colors.black,
fontSize: 16),
hintText: hintText,
isDense: true,
hintStyle: hintStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(
color: AppColor.colorHintInputCreateMailbox,
fontSize: 16),
contentPadding: contentPadding ?? const EdgeInsets.symmetric(
horizontal: 12,
vertical: 12),
errorText: errorText != '' ? errorText : null,
errorStyle: errorTextStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(
color: AppColor.colorInputBorderErrorVerifyName,
fontSize: 13),
filled: true,
fillColor: errorText?.isNotEmpty == true
? AppColor.colorInputBackgroundErrorVerifyName
: Colors.white);
}
}
@@ -1,49 +0,0 @@
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:core/presentation/views/text/text_field_builder.dart';
import 'package:core/utils/direction_utils.dart';
import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rules_filter_input_decoration_builder.dart';
typedef OnChangeFilterInputAction = Function(String? value);
class RulesFilterInputField extends StatelessWidget {
final String? errorText;
final String? hintText;
final TextEditingController? editingController;
final FocusNode? focusNode;
final OnChangeFilterInputAction? onChangeAction;
const RulesFilterInputField({
Key? key,
this.hintText,
this.errorText,
this.editingController,
this.focusNode,
this.onChangeAction
}) : super(key: key);
@override
Widget build(BuildContext context) {
return TextFieldBuilder(
onTextChange: onChangeAction,
textInputAction: TextInputAction.next,
controller: editingController,
textStyle: ThemeUtils.defaultTextStyleInterFont.copyWith(
color: Colors.black,
fontSize: 16,
),
textDirection: DirectionUtils.getDirectionByLanguage(context),
keyboardType: TextInputType.text,
focusNode: focusNode,
maxLines: 1,
decoration: (RulesFilterInputDecorationBuilder()
..setContentPadding(EdgeInsets.symmetric(vertical: PlatformInfo.isWeb ? 14 : 12, horizontal: 12))
..setHintText(hintText)
..setErrorText(errorText))
.build(),
);
}
}