TF-611 Add view email rule filter creator
This commit is contained in:
@@ -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/html_viewer/html_viewer_controller_for_web.dart';
|
||||||
export 'presentation/views/floating_button/scrolling_floating_button_animated.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_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/cupertino_action_sheet_builder.dart';
|
||||||
export 'presentation/views/bottom_popup/confirmation_dialog_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';
|
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 colorSelectedRichTextButton = Color(0x99EBEDF0);
|
||||||
static const colorShadowDestinationPicker = Color(0x33000000);
|
static const colorShadowDestinationPicker = Color(0x33000000);
|
||||||
static const colorBackgroundSnackBar = Color(0xFF343438);
|
static const colorBackgroundSnackBar = Color(0xFF343438);
|
||||||
|
static const colorBackgroundFieldConditionRulesFilter = Color(0xFFF2F3F5);
|
||||||
|
static const colorDividerRuleFilter = Color(0xFFE7E8EC);
|
||||||
|
|
||||||
static const mapGradientColor = [
|
static const mapGradientColor = [
|
||||||
[Color(0xFF21D4FD), Color(0xFFB721FF)],
|
[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:get/get.dart';
|
||||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||||
import 'package:pointer_interceptor/pointer_interceptor.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/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/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 {
|
class DropDownButtonWidget<T> extends StatelessWidget {
|
||||||
|
|
||||||
@@ -28,6 +31,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
|||||||
final Color? colorButton;
|
final Color? colorButton;
|
||||||
final String tooltip;
|
final String tooltip;
|
||||||
final double? dropdownWidth;
|
final double? dropdownWidth;
|
||||||
|
final double? dropdownMaxHeight;
|
||||||
|
|
||||||
const DropDownButtonWidget({
|
const DropDownButtonWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
@@ -43,6 +47,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
|||||||
this.opacity = 1.0,
|
this.opacity = 1.0,
|
||||||
this.iconArrowDown,
|
this.iconArrowDown,
|
||||||
this.dropdownWidth,
|
this.dropdownWidth,
|
||||||
|
this.dropdownMaxHeight,
|
||||||
this.colorButton = Colors.white,
|
this.colorButton = Colors.white,
|
||||||
this.tooltip = '',
|
this.tooltip = '',
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@@ -105,7 +110,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
|||||||
borderRadius: BorderRadius.circular(radiusButton),
|
borderRadius: BorderRadius.circular(radiusButton),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: AppColor.colorInputBorderCreateMailbox,
|
color: AppColor.colorInputBorderCreateMailbox,
|
||||||
width: 0.5,
|
width: 1,
|
||||||
),
|
),
|
||||||
color: colorButton ?? AppColor.colorInputBackgroundCreateMailbox,
|
color: colorButton ?? AppColor.colorInputBackgroundCreateMailbox,
|
||||||
),
|
),
|
||||||
@@ -132,7 +137,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
|||||||
borderRadius: BorderRadius.circular(radiusButton),
|
borderRadius: BorderRadius.circular(radiusButton),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: AppColor.colorInputBorderCreateMailbox,
|
color: AppColor.colorInputBorderCreateMailbox,
|
||||||
width: 0.5,
|
width: 1,
|
||||||
),
|
),
|
||||||
color: colorButton ?? AppColor.colorInputBackgroundCreateMailbox,
|
color: colorButton ?? AppColor.colorInputBackgroundCreateMailbox,
|
||||||
),
|
),
|
||||||
@@ -142,7 +147,7 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
|||||||
? Colors.white
|
? Colors.white
|
||||||
: Colors.black12,
|
: Colors.black12,
|
||||||
itemPadding: const EdgeInsets.symmetric(horizontal: 12),
|
itemPadding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
dropdownMaxHeight: 200,
|
dropdownMaxHeight: dropdownMaxHeight ?? 200,
|
||||||
dropdownDecoration: BoxDecoration(
|
dropdownDecoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(radiusButton),
|
borderRadius: BorderRadius.circular(radiusButton),
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@@ -171,6 +176,15 @@ class DropDownButtonWidget<T> extends StatelessWidget {
|
|||||||
if (item is enough_html_editor.SafeFont) {
|
if (item is enough_html_editor.SafeFont) {
|
||||||
return item.name;
|
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 '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
@@ -54,6 +54,7 @@ class AppBarDestinationPickerBuilder extends StatelessWidget {
|
|||||||
Widget _buildCancelButton(BuildContext context) {
|
Widget _buildCancelButton(BuildContext context) {
|
||||||
if (_mailboxAction == MailboxActions.moveEmail ||
|
if (_mailboxAction == MailboxActions.moveEmail ||
|
||||||
_mailboxAction == MailboxActions.move ||
|
_mailboxAction == MailboxActions.move ||
|
||||||
|
_mailboxAction == MailboxActions.selectFromRuleFilter ||
|
||||||
_mailboxAction == MailboxActions.select) {
|
_mailboxAction == MailboxActions.select) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(right: 12),
|
padding: const EdgeInsets.only(right: 12),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ enum MailboxActions {
|
|||||||
rename,
|
rename,
|
||||||
move,
|
move,
|
||||||
markAsRead,
|
markAsRead,
|
||||||
|
selectFromRuleFilter,
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MailboxActionsExtension on MailboxActions {
|
extension MailboxActionsExtension on MailboxActions {
|
||||||
@@ -23,6 +24,7 @@ extension MailboxActionsExtension on MailboxActions {
|
|||||||
case MailboxActions.move:
|
case MailboxActions.move:
|
||||||
return AppLocalizations.of(context).moveTo;
|
return AppLocalizations.of(context).moveTo;
|
||||||
case MailboxActions.select:
|
case MailboxActions.select:
|
||||||
|
case MailboxActions.selectFromRuleFilter:
|
||||||
return AppLocalizations.of(context).selectMailbox;
|
return AppLocalizations.of(context).selectMailbox;
|
||||||
default:
|
default:
|
||||||
return '';
|
return '';
|
||||||
@@ -82,6 +84,7 @@ extension MailboxActionsExtension on MailboxActions {
|
|||||||
case MailboxActions.moveEmail:
|
case MailboxActions.moveEmail:
|
||||||
case MailboxActions.move:
|
case MailboxActions.move:
|
||||||
case MailboxActions.select:
|
case MailboxActions.select:
|
||||||
|
case MailboxActions.selectFromRuleFilter:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -104,6 +107,7 @@ extension MailboxActionsExtension on MailboxActions {
|
|||||||
case MailboxActions.moveEmail:
|
case MailboxActions.moveEmail:
|
||||||
case MailboxActions.move:
|
case MailboxActions.move:
|
||||||
case MailboxActions.select:
|
case MailboxActions.select:
|
||||||
|
case MailboxActions.selectFromRuleFilter:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -34,4 +34,12 @@ extension ValicatorFailureExtension on VerifyNameFailure {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getMessageRulesFilter(BuildContext context) {
|
||||||
|
if (exception is EmptyNameException) {
|
||||||
|
return AppLocalizations.of(context).this_field_cannot_be_blank;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+38
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
+67
@@ -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);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+67
@@ -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);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+67
@@ -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 '';
|
||||||
|
}
|
||||||
|
}
|
||||||
+53
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+43
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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": "Initializing data...",
|
||||||
"@initializing_data": {
|
"@initializing_data": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -1789,5 +1789,95 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"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": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1840,4 +1840,97 @@ class AppLocalizations {
|
|||||||
name: 'deleteRule',
|
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',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user