TF-611 Add view email rule filter creator

This commit is contained in:
dab246
2022-08-10 17:32:35 +07:00
committed by Dat H. Pham
parent c6ec5baf9b
commit 6d327fd896
22 changed files with 1659 additions and 6 deletions
+1
View File
@@ -64,6 +64,7 @@ export 'presentation/views/html_viewer/html_content_viewer_on_web_widget.dart';
export 'presentation/views/html_viewer/html_viewer_controller_for_web.dart';
export 'presentation/views/floating_button/scrolling_floating_button_animated.dart';
export 'presentation/views/bottom_popup/cupertino_action_sheet_action_builder.dart';
export 'presentation/views/bottom_popup/cupertino_action_sheet_no_icon_builder.dart';
export 'presentation/views/bottom_popup/cupertino_action_sheet_builder.dart';
export 'presentation/views/bottom_popup/confirmation_dialog_action_sheet_builder.dart';
export 'presentation/views/modal_sheets/edit_text_modal_sheet_builder.dart';
@@ -131,6 +131,8 @@ extension AppColor on Color {
static const colorSelectedRichTextButton = Color(0x99EBEDF0);
static const colorShadowDestinationPicker = Color(0x33000000);
static const colorBackgroundSnackBar = Color(0xFF343438);
static const colorBackgroundFieldConditionRulesFilter = Color(0xFFF2F3F5);
static const colorDividerRuleFilter = Color(0xFFE7E8EC);
static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
@@ -0,0 +1,29 @@
import 'package:flutter/material.dart';
typedef OnCupertinoActionSheetNoIconActionClick<T> = void Function(T data);
abstract class CupertinoActionSheetNoIconBuilder<T> {
@protected
final Key? key;
@protected
final String actionName;
@protected
OnCupertinoActionSheetNoIconActionClick<T>? onCupertinoActionSheetActionClick;
CupertinoActionSheetNoIconBuilder(
this.actionName,
{
this.key,
}
);
void onActionClick(OnCupertinoActionSheetNoIconActionClick<T> onCupertinoActionSheetActionClick) {
this.onCupertinoActionSheetActionClick = onCupertinoActionSheetActionClick;
}
TextStyle actionTextStyle({TextStyle? textStyle}) {
return textStyle ?? TextStyle(fontSize: 17, color: Colors.black);
}
Widget build();
}
@@ -9,8 +9,11 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition;
import 'package:tmail_ui_user/features/composer/presentation/model/font_name_type.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/language_and_region/extensions/locale_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/model/email_rule_filter_action.dart';
class DropDownButtonWidget<T> extends StatelessWidget {
@@ -28,6 +31,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
final Color? colorButton;
final String tooltip;
final double? dropdownWidth;
final double? dropdownMaxHeight;
const DropDownButtonWidget({
Key? key,
@@ -43,6 +47,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
this.opacity = 1.0,
this.iconArrowDown,
this.dropdownWidth,
this.dropdownMaxHeight,
this.colorButton = Colors.white,
this.tooltip = '',
}) : super(key: key);
@@ -105,7 +110,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
borderRadius: BorderRadius.circular(radiusButton),
border: Border.all(
color: AppColor.colorInputBorderCreateMailbox,
width: 0.5,
width: 1,
),
color: colorButton ?? AppColor.colorInputBackgroundCreateMailbox,
),
@@ -132,7 +137,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
borderRadius: BorderRadius.circular(radiusButton),
border: Border.all(
color: AppColor.colorInputBorderCreateMailbox,
width: 0.5,
width: 1,
),
color: colorButton ?? AppColor.colorInputBackgroundCreateMailbox,
),
@@ -142,7 +147,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
? Colors.white
: Colors.black12,
itemPadding: const EdgeInsets.symmetric(horizontal: 12),
dropdownMaxHeight: 200,
dropdownMaxHeight: dropdownMaxHeight ?? 200,
dropdownDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(radiusButton),
color: Colors.white,
@@ -171,6 +176,15 @@ class DropDownButtonWidget<T> extends StatelessWidget {
if (item is enough_html_editor.SafeFont) {
return item.name;
}
if (item is rule_condition.Field) {
return item.getTitle(context);
}
if (item is rule_condition.Comparator) {
return item.getTitle(context);
}
if (item is EmailRuleFilterAction) {
return item.getTitle(context);
}
return '';
}
}
@@ -54,6 +54,7 @@ class AppBarDestinationPickerBuilder extends StatelessWidget {
Widget _buildCancelButton(BuildContext context) {
if (_mailboxAction == MailboxActions.moveEmail ||
_mailboxAction == MailboxActions.move ||
_mailboxAction == MailboxActions.selectFromRuleFilter ||
_mailboxAction == MailboxActions.select) {
return Padding(
padding: const EdgeInsets.only(right: 12),
@@ -11,6 +11,7 @@ enum MailboxActions {
rename,
move,
markAsRead,
selectFromRuleFilter,
}
extension MailboxActionsExtension on MailboxActions {
@@ -23,6 +24,7 @@ extension MailboxActionsExtension on MailboxActions {
case MailboxActions.move:
return AppLocalizations.of(context).moveTo;
case MailboxActions.select:
case MailboxActions.selectFromRuleFilter:
return AppLocalizations.of(context).selectMailbox;
default:
return '';
@@ -82,6 +84,7 @@ extension MailboxActionsExtension on MailboxActions {
case MailboxActions.moveEmail:
case MailboxActions.move:
case MailboxActions.select:
case MailboxActions.selectFromRuleFilter:
return true;
default:
return false;
@@ -104,6 +107,7 @@ extension MailboxActionsExtension on MailboxActions {
case MailboxActions.moveEmail:
case MailboxActions.move:
case MailboxActions.select:
case MailboxActions.selectFromRuleFilter:
return false;
default:
return true;
@@ -34,4 +34,12 @@ extension ValicatorFailureExtension on VerifyNameFailure {
return '';
}
}
String getMessageRulesFilter(BuildContext context) {
if (exception is EmptyNameException) {
return AppLocalizations.of(context).this_field_cannot_be_blank;
} else {
return '';
}
}
}
@@ -0,0 +1,38 @@
import 'package:flutter/cupertino.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition;
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
extension RuleConditionFieldExtension on rule_condition.Field {
String getTitle(BuildContext context) {
switch(this) {
case rule_condition.Field.from:
return AppLocalizations.of(context).ruleFilterAddressFromField;
case rule_condition.Field.to:
return AppLocalizations.of(context).ruleFilterAddressToField;
case rule_condition.Field.cc:
return AppLocalizations.of(context).ruleFilterAddressCcField;
case rule_condition.Field.recipient:
return AppLocalizations.of(context).recipient;
case rule_condition.Field.subject:
return AppLocalizations.of(context).subject;
}
}
}
extension RuleConditionComparatorExtension on rule_condition.Comparator {
String getTitle(BuildContext context) {
switch(this) {
case rule_condition.Comparator.contains:
return AppLocalizations.of(context).contains;
case rule_condition.Comparator.notContains:
return AppLocalizations.of(context).notContains;
case rule_condition.Comparator.exactlyEquals:
return AppLocalizations.of(context).exactlyEquals;
case rule_condition.Comparator.notExactlyEquals:
return AppLocalizations.of(context).notExactlyEquals;
}
}
}
@@ -0,0 +1,22 @@
import 'package:core/presentation/extensions/capitalize_extension.dart';
import 'package:flutter/material.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
enum CreatorActionType {
create;
String getTitle(BuildContext context) {
switch(this) {
case CreatorActionType.create:
return AppLocalizations.of(context).createNewRule.inCaps;
}
}
String getActionName(BuildContext context) {
switch(this) {
case CreatorActionType.create:
return AppLocalizations.of(context).create.inCaps;
}
}
}
@@ -0,0 +1,15 @@
import 'package:flutter/cupertino.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
enum EmailRuleFilterAction {
moveMessage;
String getTitle(BuildContext context) {
switch(this) {
case EmailRuleFilterAction.moveMessage:
return AppLocalizations.of(context).moveMessage;
}
}
}
@@ -0,0 +1,16 @@
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/creator_action_type.dart';
class RulesFilterCreatorArguments with EquatableMixin {
final AccountId accountId;
final CreatorActionType actionType;
RulesFilterCreatorArguments(this.accountId, {
this.actionType = CreatorActionType.create
});
@override
List<Object?> get props => [accountId, actionType];
}
@@ -0,0 +1,36 @@
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/base_bindings.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_controller.dart';
class RulesFilterCreatorBindings extends BaseBindings {
@override
void bindingsController() {
Get.lazyPut(() => RulesFilterCreatorController(
Get.find<VerifyNameInteractor>()
));
}
@override
void bindingsDataSource() {
}
@override
void bindingsDataSourceImpl() {
}
@override
void bindingsInteractor() {
Get.lazyPut(() => VerifyNameInteractor());
}
@override
void bindingsRepository() {
}
@override
void bindingsRepositoryImpl() {
}
}
@@ -0,0 +1,191 @@
import 'package:core/utils/app_logger.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:model/model.dart';
import 'package:rule_filter/rule_filter/rule_action.dart';
import 'package:rule_filter/rule_filter/rule_append_in.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition;
import 'package:rule_filter/rule_filter/tmail_rule.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/empty_name_validator.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/state/verify_name_view_state.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_creator/presentation/extensions/validator_failure_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/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/rules_filter_creator_arguments.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class RulesFilterCreatorController extends BaseController {
final VerifyNameInteractor _verifyNameInteractor;
final actionType = CreatorActionType.create.obs;
final errorRuleName = Rxn<String>();
final errorConditionValue = Rxn<String>();
final ruleConditionFieldSelected = Rxn<rule_condition.Field>();
final ruleConditionComparatorSelected = Rxn<rule_condition.Comparator>();
final emailRuleFilterActionSelected = Rxn<EmailRuleFilterAction>();
final mailboxSelected = Rxn<PresentationMailbox>();
final isCreateRuleFilterValid = RxBool(false);
final inputRuleNameController = TextEditingController();
final inputConditionValueController = TextEditingController();
AccountId? _accountId;
String? _newRuleName;
String? _newConditionValue;
RulesFilterCreatorController(this._verifyNameInteractor);
@override
void onReady() {
_getArguments();
_setUpDefaultValueRuleFilter();
super.onReady();
}
@override
void onClose() {
inputRuleNameController.dispose();
inputConditionValueController.dispose();
super.onClose();
}
@override
void onDone() {}
@override
void onError(error) {}
void _getArguments() {
final arguments = Get.arguments;
if (arguments is RulesFilterCreatorArguments) {
_accountId = arguments.accountId;
actionType.value = arguments.actionType;
}
}
void _setUpDefaultValueRuleFilter() {
if (actionType.value == CreatorActionType.create) {
ruleConditionFieldSelected.value = rule_condition.Field.from;
ruleConditionComparatorSelected.value = rule_condition.Comparator.exactlyEquals;
emailRuleFilterActionSelected.value = EmailRuleFilterAction.moveMessage;
}
_updateStateCreatorButton();
}
void updateRuleName(BuildContext context, String? value) {
_newRuleName = value;
errorRuleName.value = _getErrorStringByInputValue(context, _newRuleName);
_updateStateCreatorButton();
}
void updateConditionValue(BuildContext context, String? value) {
_newConditionValue = value;
errorConditionValue.value = _getErrorStringByInputValue(context, _newConditionValue);
_updateStateCreatorButton();
}
String? _getErrorStringByInputValue(BuildContext context, String? inputValue) {
return _verifyNameInteractor.execute(inputValue, [EmptyNameValidator()]).fold(
(failure) {
if (failure is VerifyNameFailure) {
return failure.getMessageRulesFilter(context);
} else {
return null;
}
},
(success) => null
);
}
void selectRuleConditionField(rule_condition.Field? newField) {
ruleConditionFieldSelected.value = newField;
_updateStateCreatorButton();
}
void selectRuleConditionComparator(rule_condition.Comparator? newComparator) {
ruleConditionComparatorSelected.value = newComparator;
_updateStateCreatorButton();
}
void selectEmailRuleFilterAction(EmailRuleFilterAction? newAction) {
emailRuleFilterActionSelected.value = newAction;
_updateStateCreatorButton();
}
void selectMailbox() async {
final destinationMailbox = await push(
AppRoutes.DESTINATION_PICKER,
arguments: DestinationPickerArguments(
_accountId!,
MailboxActions.selectForRuleAction));
if (destinationMailbox is PresentationMailbox) {
mailboxSelected.value = destinationMailbox;
_updateStateCreatorButton();
}
}
void _updateStateCreatorButton() {
isCreateRuleFilterValid.value = _newRuleName?.trim().isNotEmpty == true &&
_newConditionValue?.trim().isNotEmpty == true &&
mailboxSelected.value != null &&
ruleConditionFieldSelected.value != null &&
emailRuleFilterActionSelected.value != null &&
ruleConditionComparatorSelected.value != null;
}
void createNewRuleFilter(BuildContext context) async {
FocusScope.of(context).unfocus();
final errorName = _getErrorStringByInputValue(context, _newRuleName);
if (errorName?.isNotEmpty == true) {
log('RulesFilterCreatorController::createNewRuleFilter(): errorName: $errorName');
errorRuleName.value = errorName;
return;
}
final errorCondition = _getErrorStringByInputValue(context, _newConditionValue);
if (errorCondition?.isNotEmpty == true) {
log('RulesFilterCreatorController::createNewRuleFilter(): errorCondition: $errorCondition');
errorConditionValue.value = errorName;
return;
}
final newTMailRule = TMailRule(
name: _newRuleName!,
action: RuleAction(
appendIn: RuleAppendIn(
mailboxIds: [mailboxSelected.value!.id]
)
),
condition: rule_condition.RuleCondition(
field: ruleConditionFieldSelected.value!,
comparator: ruleConditionComparatorSelected.value!,
value: _newConditionValue!
));
log('RulesFilterCreatorController::newTMailRule(): $newTMailRule');
_clearAll();
popBack(result: newTMailRule);
}
void _clearAll() {
inputRuleNameController.clear();
inputConditionValueController.clear();
}
void closeView(BuildContext context) {
FocusScope.of(context).unfocus();
popBack();
}
}
@@ -0,0 +1,723 @@
import 'package:core/core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:model/model.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition;
import 'package:tmail_ui_user/features/base/widget/drop_down_button_widget.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/extensions/rule_condition_extensions.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_controller.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_action_bottom_sheet_action_tile_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_condition_comparator_bottom_sheet_action_tile_builder.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/widgets/rule_condition_field_bottom_sheet_action_tile_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/rules_filter_input_field_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class RuleFilterCreatorView extends GetWidget<RulesFilterCreatorController> {
final _imagePaths = Get.find<ImagePaths>();
final _responsiveUtils = Get.find<ResponsiveUtils>();
RuleFilterCreatorView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ResponsiveWidget(
responsiveUtils: _responsiveUtils,
mobile: Scaffold(
backgroundColor: Colors.black38,
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: SafeArea(
child: Align(
alignment: Alignment.bottomCenter,
child: Card(
color: Colors.transparent,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
)),
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
)),
width: double.infinity,
height: _responsiveUtils.getSizeScreenHeight(context) - 70,
child: ClipRRect(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16)),
child: _buildRulesFilterFormOnMobile(context)
)
)
)
),
),
)
),
tablet: Scaffold(
backgroundColor: Colors.black38,
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Align(alignment: Alignment.bottomCenter, child: Card(
color: Colors.transparent,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
)),
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
)),
width: double.infinity,
height: _responsiveUtils.getSizeScreenHeight(context) * 0.7,
child: ClipRRect(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16)),
child: _buildRulesFilterFormOnTablet(context)
)
)
)),
)
),
desktop: Scaffold(
backgroundColor: Colors.black38,
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Align(alignment: Alignment.center, child: Card(
color: Colors.transparent,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16))),
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(16))),
width: _responsiveUtils.getSizeScreenWidth(context) * 0.6,
height: _responsiveUtils.getSizeScreenHeight(context) * 0.7,
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(16)),
child: _buildRulesFilterFormOnDesktop(context)
)
)
)
),
)
)
);
}
Widget _buildRulesFilterFormOnDesktop(BuildContext context) {
return Stack(
children: [
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Container(
padding: const EdgeInsets.only(top: 16),
alignment: Alignment.center,
child: Obx(() => Text(
controller.actionType.value.getTitle(context),
style: const TextStyle(
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,
onChangeAction: (value) => controller.updateRuleName(context, value),)),
const SizedBox(height: 24),
Text(AppLocalizations.of(context).conditionTitleRulesFilter,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black)),
const SizedBox(height: 24),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColor.colorBackgroundFieldConditionRulesFilter,
borderRadius: BorderRadius.circular(12)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: Obx(() => DropDownButtonWidget<rule_condition.Field>(
items: rule_condition.Field.values,
itemSelected: controller.ruleConditionFieldSelected.value,
dropdownMaxHeight: 250,
onChanged: (newField) =>
controller.selectRuleConditionField(newField),
supportSelectionIcon: true))),
Container(
width: 220,
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Obx(() => DropDownButtonWidget<rule_condition.Comparator>(
items: rule_condition.Comparator.values,
itemSelected: controller.ruleConditionComparatorSelected.value,
onChanged: (newComparator) =>
controller.selectRuleConditionComparator(newComparator),
supportSelectionIcon: true))),
Expanded(child: Obx(() => RulesFilterInputField(
hintText: AppLocalizations.of(context).conditionValueHintTextInput,
errorText: controller.errorConditionValue.value,
editingController: controller.inputConditionValueController,
onChangeAction: (value) =>
controller.updateConditionValue(context, value))))
]
)
),
const SizedBox(height: 24),
Text(AppLocalizations.of(context).actionTitleRulesFilter,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black)),
const SizedBox(height: 24),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColor.colorBackgroundFieldConditionRulesFilter,
borderRadius: BorderRadius.circular(12)),
child: Row(children: [
Expanded(child: Obx(() => DropDownButtonWidget<EmailRuleFilterAction>(
items: EmailRuleFilterAction.values,
itemSelected: controller.emailRuleFilterActionSelected.value,
onChanged: (newAction) =>
controller.selectEmailRuleFilterAction(newAction),
supportSelectionIcon: true))),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text(
AppLocalizations.of(context).toMailbox,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 16,
color: Colors.black)),
),
Expanded(child: Obx(() =>
RuleFilterButtonField<PresentationMailbox>(
value: controller.mailboxSelected.value,
tapActionCallback: (value) => controller.selectMailbox()))),
])
),
]
),
),
)),
Container(
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
alignment: Alignment.centerRight,
color: Colors.white,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
buildTextButton(
AppLocalizations.of(context).cancel,
textStyle: const TextStyle(
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),
Obx(() => buildTextButton(
controller.actionType.value.getActionName(context),
width: 128,
height: 44,
backgroundColor: AppColor.colorTextButton
.withOpacity(controller.isCreateRuleFilterValid.value
? 1.0
: 0.4),
radius: 10,
onTap: () {
if (controller.isCreateRuleFilterValid.value) {
controller.createNewRuleFilter(context);
}
})),
]
),
)
]),
Positioned(top: 8, right: 8,
child: buildIconWeb(
icon: SvgPicture.asset(
_imagePaths.icCloseMailbox,
fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
onTap: () => controller.closeView(context)))
]
);
}
Widget _buildRulesFilterFormOnTablet(BuildContext context) {
return Stack(
children: [
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Container(
padding: const EdgeInsets.only(top: 16),
alignment: Alignment.center,
child: Obx(() => Text(
controller.actionType.value.getTitle(context),
style: const TextStyle(
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,
onChangeAction: (value) => controller.updateRuleName(context, value),)),
const SizedBox(height: 24),
Text(AppLocalizations.of(context).conditionTitleRulesFilter,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black)),
const SizedBox(height: 24),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColor.colorBackgroundFieldConditionRulesFilter,
borderRadius: BorderRadius.circular(12)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: Obx(() => DropDownButtonWidget<rule_condition.Field>(
items: rule_condition.Field.values,
itemSelected: controller.ruleConditionFieldSelected.value,
dropdownMaxHeight: 250,
onChanged: (newField) =>
controller.selectRuleConditionField(newField),
supportSelectionIcon: true))),
Container(
width: 220,
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Obx(() => DropDownButtonWidget<rule_condition.Comparator>(
items: rule_condition.Comparator.values,
itemSelected: controller.ruleConditionComparatorSelected.value,
onChanged: (newComparator) =>
controller.selectRuleConditionComparator(newComparator),
supportSelectionIcon: true))),
Expanded(child: Obx(() => RulesFilterInputField(
hintText: AppLocalizations.of(context).conditionValueHintTextInput,
errorText: controller.errorConditionValue.value,
editingController: controller.inputConditionValueController,
onChangeAction: (value) =>
controller.updateConditionValue(context, value))))
]
)
),
const SizedBox(height: 24),
Text(AppLocalizations.of(context).actionTitleRulesFilter,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black)),
const SizedBox(height: 24),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColor.colorBackgroundFieldConditionRulesFilter,
borderRadius: BorderRadius.circular(12)),
child: Row(children: [
Expanded(child: Obx(() => DropDownButtonWidget<EmailRuleFilterAction>(
items: EmailRuleFilterAction.values,
itemSelected: controller.emailRuleFilterActionSelected.value,
onChanged: (newAction) =>
controller.selectEmailRuleFilterAction(newAction),
supportSelectionIcon: true))),
Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text(
AppLocalizations.of(context).toMailbox,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 16,
color: Colors.black)),
),
Expanded(child: Obx(() =>
RuleFilterButtonField<PresentationMailbox>(
value: controller.mailboxSelected.value,
tapActionCallback: (value) => controller.selectMailbox()))),
])
),
]
),
),
)),
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: const TextStyle(
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
.withOpacity(controller.isCreateRuleFilterValid.value
? 1.0
: 0.4),
radius: 10,
onTap: () {
if (controller.isCreateRuleFilterValid.value) {
controller.createNewRuleFilter(context);
}
}))),
]
),
)
]),
Positioned(top: 8, right: 8,
child: buildIconWeb(
icon: SvgPicture.asset(
_imagePaths.icCloseMailbox,
fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
onTap: () => controller.closeView(context)))
]
);
}
Widget _buildRulesFilterFormOnMobile(BuildContext context) {
return Stack(
children: [
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Container(
padding: const EdgeInsets.only(top: 16),
alignment: Alignment.center,
child: Obx(() => Text(
controller.actionType.value.getTitle(context),
style: const TextStyle(
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,
onChangeAction: (value) => controller.updateRuleName(context, value),)),
const Padding(
padding: EdgeInsets.symmetric(vertical: 12),
child: Divider(
color: AppColor.colorDividerRuleFilter,
height: 1,
thickness: 0.2),
),
Text(AppLocalizations.of(context).conditionTitleRulesFilter,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black)),
const SizedBox(height: 24),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColor.colorBackgroundFieldConditionRulesFilter,
borderRadius: BorderRadius.circular(12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Obx(() {
return RuleFilterButtonField<rule_condition.Field>(
value: controller.ruleConditionFieldSelected.value,
tapActionCallback: (value) =>
controller.openContextMenuAction(
context,
_bottomSheetRuleConditionFieldActionTiles(
context,
controller.ruleConditionFieldSelected.value))
);
}),
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Obx(() {
return RuleFilterButtonField<rule_condition.Comparator>(
value: controller.ruleConditionComparatorSelected.value,
tapActionCallback: (value) =>
controller.openContextMenuAction(
context,
_bottomSheetRuleConditionComparatorActionTiles(
context,
controller.ruleConditionComparatorSelected.value))
);
}),
),
Obx(() => RulesFilterInputField(
hintText: AppLocalizations.of(context).conditionValueHintTextInput,
errorText: controller.errorConditionValue.value,
editingController: controller.inputConditionValueController,
onChangeAction: (value) =>
controller.updateConditionValue(context, value)))
]
)
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 12),
child: Divider(
color: AppColor.colorDividerRuleFilter,
height: 1),
),
Text(AppLocalizations.of(context).actionTitleRulesFilter,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.black)),
const SizedBox(height: 24),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColor.colorBackgroundFieldConditionRulesFilter,
borderRadius: BorderRadius.circular(12)),
child: Column(children: [
Obx(() {
return RuleFilterButtonField<EmailRuleFilterAction>(
value: controller.emailRuleFilterActionSelected.value,
tapActionCallback: (value) =>
controller.openContextMenuAction(
context,
_bottomSheetActionRuleFilterActionTiles(
context,
controller.emailRuleFilterActionSelected.value))
);
}),
Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
AppLocalizations.of(context).toMailbox,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 16,
color: Colors.black)),
),
Obx(() => RuleFilterButtonField<PresentationMailbox>(
value: controller.mailboxSelected.value,
tapActionCallback: (value) => controller.selectMailbox()))
])
),
]
),
),
)),
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: const TextStyle(
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
.withOpacity(controller.isCreateRuleFilterValid.value
? 1.0
: 0.4),
radius: 10,
onTap: () {
if (controller.isCreateRuleFilterValid.value) {
controller.createNewRuleFilter(context);
}
}))),
]
),
)
]),
Positioned(top: 8, right: 8,
child: buildIconWeb(
icon: SvgPicture.asset(
_imagePaths.icCloseMailbox,
fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
onTap: () => controller.closeView(context)))
]
);
}
List<Widget> _bottomSheetRuleConditionFieldActionTiles(
BuildContext context,
rule_condition.Field? fieldSelected
) {
return rule_condition.Field.values
.map((field) =>
_buildRuleConditionFieldWidget(context, field, fieldSelected))
.toList();
}
Widget _buildRuleConditionFieldWidget(
BuildContext context,
rule_condition.Field field,
rule_condition.Field? fieldSelected
) {
return (RuleConditionFieldSheetActionTileBuilder(
field.getTitle(context),
fieldSelected,
field,
iconLeftPadding: const EdgeInsets.only(left: 12, right: 16),
iconRightPadding: const EdgeInsets.only(right: 12),
actionSelected: SvgPicture.asset(
_imagePaths.icFilterSelected,
width: 20,
height: 20,
fit: BoxFit.fill))
..onActionClick((field) {
controller.selectRuleConditionField(field);
popBack();
}))
.build();
}
List<Widget> _bottomSheetRuleConditionComparatorActionTiles(
BuildContext context,
rule_condition.Comparator? comparatorSelected
) {
return rule_condition.Comparator.values
.map((comparator) =>
_buildRuleConditionComparatorWidget(context, comparator, comparatorSelected))
.toList();
}
Widget _buildRuleConditionComparatorWidget(
BuildContext context,
rule_condition.Comparator comparator,
rule_condition.Comparator? comparatorSelected
) {
return (RuleConditionComparatorSheetActionTileBuilder(
comparator.getTitle(context),
comparatorSelected,
comparator,
iconLeftPadding: const EdgeInsets.only(left: 12, right: 16),
iconRightPadding: const EdgeInsets.only(right: 12),
actionSelected: SvgPicture.asset(
_imagePaths.icFilterSelected,
width: 20,
height: 20,
fit: BoxFit.fill))
..onActionClick((comparator) {
controller.selectRuleConditionComparator(comparator);
popBack();
}))
.build();
}
List<Widget> _bottomSheetActionRuleFilterActionTiles(
BuildContext context,
EmailRuleFilterAction? ruleActionSelected
) {
return EmailRuleFilterAction.values
.map((ruleAction) =>
_buildRuleActionWidget(context, ruleAction, ruleActionSelected))
.toList();
}
Widget _buildRuleActionWidget(
BuildContext context,
EmailRuleFilterAction ruleAction,
EmailRuleFilterAction? ruleActionSelected
) {
return (RuleActionSheetActionTileBuilder(
ruleAction.getTitle(context),
ruleActionSelected,
ruleAction,
iconLeftPadding: const EdgeInsets.only(left: 12, right: 16),
iconRightPadding: const EdgeInsets.only(right: 12),
actionSelected: SvgPicture.asset(
_imagePaths.icFilterSelected,
width: 20,
height: 20,
fit: BoxFit.fill))
..onActionClick((ruleAction) {
controller.selectEmailRuleFilterAction(ruleAction);
popBack();
}))
.build();
}
}
@@ -0,0 +1,67 @@
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: BuildUtils.isWeb
? MaterialStateMouseCursor.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);
}
},
),
),
);
}
}
@@ -0,0 +1,67 @@
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: BuildUtils.isWeb
? MaterialStateMouseCursor.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);
}
},
),
),
);
}
}
@@ -0,0 +1,67 @@
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: BuildUtils.isWeb
? MaterialStateMouseCursor.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);
}
},
),
),
);
}
}
@@ -0,0 +1,73 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/style_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:model/model.dart';
import 'package:rule_filter/rule_filter/rule_condition.dart' as rule_condition;
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/extensions/rule_condition_extensions.dart';
import 'package:tmail_ui_user/features/rules_filter_creator/presentation/model/email_rule_filter_action.dart';
typedef OnTapActionCallback<T> = Function(T? value);
class RuleFilterButtonField<T> extends StatelessWidget {
final T? value;
final OnTapActionCallback? tapActionCallback;
const RuleFilterButtonField({
super.key,
this.value,
this.tapActionCallback
});
@override
Widget build(BuildContext context) {
final _imagePaths = Get.find<ImagePaths>();
return InkWell(
onTap: () => tapActionCallback?.call(value),
child: Container(
height: 44,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: AppColor.colorInputBorderCreateMailbox,
width: 1),
color: Colors.white),
padding: const EdgeInsets.only(left: 12, right: 10),
child: Row(children: [
Expanded(child: Text(
_getName(context, value),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black),
maxLines: 1,
softWrap: CommonTextStyle.defaultSoftWrap,
overflow: CommonTextStyle.defaultTextOverFlow,
)),
SvgPicture.asset(_imagePaths.icDropDown)
]),
),
);
}
String _getName(BuildContext context, T? value) {
if (value is PresentationMailbox) {
return value.name?.name ?? '';
}
if (value is rule_condition.Field) {
return value.getTitle(context);
}
if (value is rule_condition.Comparator) {
return value.getTitle(context);
}
if (value is EmailRuleFilterAction) {
return value.getTitle(context);
}
return '';
}
}
@@ -0,0 +1,53 @@
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 ?? const TextStyle(
color: Colors.black,
fontSize: 16),
hintText: hintText,
isDense: true,
hintStyle: hintStyle ?? const TextStyle(
color: AppColor.colorHintInputCreateMailbox,
fontSize: 16),
contentPadding: contentPadding ?? const EdgeInsets.symmetric(
horizontal: 12,
vertical: 12),
errorText: errorText,
errorStyle: errorTextStyle ?? const TextStyle(
color: AppColor.colorInputBorderErrorVerifyName,
fontSize: 13),
filled: true,
fillColor: errorText?.isNotEmpty == true
? AppColor.colorInputBackgroundErrorVerifyName
: Colors.white);
}
}
@@ -0,0 +1,43 @@
import 'package:core/presentation/views/text/text_field_builder.dart';
import 'package:core/utils/build_utils.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 bool isMandatory;
final OnChangeFilterInputAction? onChangeAction;
const RulesFilterInputField({
Key? key,
this.hintText,
this.errorText,
this.isMandatory = false,
this.editingController,
this.onChangeAction
}) : super(key: key);
@override
Widget build(BuildContext context) {
return (TextFieldBuilder()
..onChange((value) => onChangeAction?.call(value))
..textInputAction(TextInputAction.next)
..addController(editingController ?? TextEditingController())
..textStyle(const TextStyle(color: Colors.black, fontSize: 16))
..keyboardType(TextInputType.text)
..textDecoration((RulesFilterInputDecorationBuilder()
..setContentPadding(const EdgeInsets.symmetric(
vertical: BuildUtils.isWeb ? 16 : 12,
horizontal: 12))
..setHintText(hintText)
..setErrorText(errorText))
.build()))
.build();
}
}
+91 -1
View File
@@ -1,5 +1,5 @@
{
"@@last_modified": "2022-08-09T16:48:03.746319",
"@@last_modified": "2022-08-10T18:05:32.066682",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -1789,5 +1789,95 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"createNewRule": "Create new rule",
"@createNewRule": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"rulesNameHintTextInput": "Enter the rule name",
"@rulesNameHintTextInput": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"conditionValueHintTextInput": "Value",
"@conditionValueHintTextInput": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"conditionTitleRulesFilter": "If all of the following conditions are met:",
"@conditionTitleRulesFilter": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"recipient": "Recipient",
"@recipient": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"contains": "Contains",
"@contains": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"notContains": "Not contains",
"@notContains": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"exactlyEquals": "Exactly equals",
"@exactlyEquals": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"notExactlyEquals": "Not exactly equals",
"@notExactlyEquals": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"actionTitleRulesFilter": "Perform the following actions:",
"@actionTitleRulesFilter": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"toMailbox": "To mailbox:",
"@toMailbox": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"moveMessage": "Move message",
"@moveMessage": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"ruleFilterAddressFromField": "From",
"@ruleFilterAddressFromField": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"ruleFilterAddressToField": "To",
"@ruleFilterAddressToField": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"ruleFilterAddressCcField": "Cc",
"@ruleFilterAddressCcField": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
+95 -2
View File
@@ -32,11 +32,11 @@ class AppLocalizations {
String get loginInputUrlMessage {
return Intl.message('To login and access your message please connect to your JMAP server', name: 'loginInputUrlMessage');
}
String get loginInputCredentialMessage {
return Intl.message('Enter your credentials to sign in', name: 'loginInputCredentialMessage');
}
String get next {
return Intl.message('Next', name: 'next');
}
@@ -1840,4 +1840,97 @@ class AppLocalizations {
name: 'deleteRule',
);
}
String get createNewRule {
return Intl.message(
'Create new rule',
name: 'createNewRule');
}
String get rulesNameHintTextInput {
return Intl.message(
'Enter the rule name',
name: 'rulesNameHintTextInput');
}
String get conditionValueHintTextInput {
return Intl.message(
'Value',
name: 'conditionValueHintTextInput');
}
String get conditionTitleRulesFilter {
return Intl.message(
'If all of the following conditions are met:',
name: 'conditionTitleRulesFilter');
}
String get recipient {
return Intl.message(
'Recipient',
name: 'recipient');
}
String get contains {
return Intl.message(
'Contains',
name: 'contains');
}
String get notContains {
return Intl.message(
'Not contains',
name: 'notContains');
}
String get exactlyEquals {
return Intl.message(
'Exactly equals',
name: 'exactlyEquals');
}
String get notExactlyEquals {
return Intl.message(
'Not exactly equals',
name: 'notExactlyEquals');
}
String get actionTitleRulesFilter {
return Intl.message(
'Perform the following actions:',
name: 'actionTitleRulesFilter');
}
String get toMailbox {
return Intl.message(
'To mailbox:',
name: 'toMailbox');
}
String get moveMessage {
return Intl.message(
'Move message',
name: 'moveMessage');
}
String get ruleFilterAddressFromField {
return Intl.message(
'From',
name: 'ruleFilterAddressFromField',
);
}
String get ruleFilterAddressToField {
return Intl.message(
'To',
name: 'ruleFilterAddressToField',
);
}
String get ruleFilterAddressCcField {
return Intl.message(
'Cc',
name: 'ruleFilterAddressCcField',
);
}
}