TF-933 Add contact From/To button to search filter
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/filter/filter_operator.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/filter/operator/logic_filter_operator.dart';
|
||||
@@ -7,9 +8,11 @@ import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart';
|
||||
import 'package:model/model.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_receive_time_type.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
class SimpleSearchFilter with EquatableMixin {
|
||||
final Set<String> from;
|
||||
final Set<String> to;
|
||||
final SearchQuery? text;
|
||||
final PresentationMailbox? mailbox;
|
||||
final EmailReceiveTimeType emailReceiveTimeType;
|
||||
@@ -18,17 +21,20 @@ class SimpleSearchFilter with EquatableMixin {
|
||||
|
||||
SimpleSearchFilter({
|
||||
Set<String>? from,
|
||||
Set<String>? to,
|
||||
EmailReceiveTimeType? emailReceiveTimeType,
|
||||
bool? hasAttachment,
|
||||
this.text,
|
||||
this.before,
|
||||
this.mailbox,
|
||||
}) : from = from ?? <String>{},
|
||||
to = to ?? <String>{},
|
||||
hasAttachment = hasAttachment ?? false,
|
||||
emailReceiveTimeType = emailReceiveTimeType ?? EmailReceiveTimeType.allTime;
|
||||
|
||||
SimpleSearchFilter copyWith({
|
||||
Set<String>? from,
|
||||
Set<String>? to,
|
||||
SearchQuery? text,
|
||||
PresentationMailbox? mailbox,
|
||||
EmailReceiveTimeType? emailReceiveTimeType,
|
||||
@@ -37,6 +43,7 @@ class SimpleSearchFilter with EquatableMixin {
|
||||
}) {
|
||||
return SimpleSearchFilter(
|
||||
from: from ?? this.from,
|
||||
to: to ?? this.to,
|
||||
text: text ?? this.text,
|
||||
mailbox: mailbox ?? this.mailbox,
|
||||
emailReceiveTimeType: emailReceiveTimeType ?? this.emailReceiveTimeType,
|
||||
@@ -63,6 +70,10 @@ class SimpleSearchFilter with EquatableMixin {
|
||||
LogicFilterOperator(
|
||||
Operator.AND,
|
||||
from.map((e) => EmailFilterCondition(from: e)).toSet()),
|
||||
if (to.isNotEmpty)
|
||||
LogicFilterOperator(
|
||||
Operator.AND,
|
||||
to.map((e) => EmailFilterCondition(to: e)).toSet()),
|
||||
};
|
||||
|
||||
return listEmailCondition.isNotEmpty
|
||||
@@ -71,7 +82,7 @@ class SimpleSearchFilter with EquatableMixin {
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [from, text, mailbox, emailReceiveTimeType, hasAttachment, before];
|
||||
List<Object?> get props => [from, to, text, mailbox, emailReceiveTimeType, hasAttachment, before];
|
||||
}
|
||||
|
||||
extension SearchEmailFilterExtension on SimpleSearchFilter {
|
||||
@@ -79,6 +90,7 @@ extension SearchEmailFilterExtension on SimpleSearchFilter {
|
||||
SimpleSearchFilter toSimpleSearchFilterByBefore({UTCDate? newBefore}) {
|
||||
return SimpleSearchFilter(
|
||||
from: from,
|
||||
to: to,
|
||||
text: text,
|
||||
mailbox: mailbox,
|
||||
emailReceiveTimeType: emailReceiveTimeType,
|
||||
@@ -100,5 +112,53 @@ extension SearchEmailFilterExtension on SimpleSearchFilter {
|
||||
|
||||
bool get searchFilterByMailboxApplied => mailbox != null;
|
||||
|
||||
bool get searchFilterByFromApplied => from.isNotEmpty;
|
||||
|
||||
bool get searchFilterByToApplied => to.isNotEmpty;
|
||||
|
||||
bool searchFilterByContactApplied(PrefixEmailAddress prefixEmailAddress) {
|
||||
switch(prefixEmailAddress) {
|
||||
case PrefixEmailAddress.from:
|
||||
return searchFilterByFromApplied;
|
||||
case PrefixEmailAddress.to:
|
||||
return searchFilterByToApplied;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> getContactApplied(PrefixEmailAddress prefixEmailAddress) {
|
||||
switch(prefixEmailAddress) {
|
||||
case PrefixEmailAddress.from:
|
||||
return from;
|
||||
case PrefixEmailAddress.to:
|
||||
return to;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
String getNameContactApplied(PrefixEmailAddress prefixEmailAddress) {
|
||||
switch(prefixEmailAddress) {
|
||||
case PrefixEmailAddress.from:
|
||||
return from.first;
|
||||
case PrefixEmailAddress.to:
|
||||
return to.first;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
String getNameContactDefault(BuildContext context, PrefixEmailAddress prefixEmailAddress) {
|
||||
switch(prefixEmailAddress) {
|
||||
case PrefixEmailAddress.from:
|
||||
return AppLocalizations.of(context).from_email_address_prefix;
|
||||
case PrefixEmailAddress.to:
|
||||
return AppLocalizations.of(context).to_email_address_prefix;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
String get mailboxName => mailbox?.name?.name ?? '';
|
||||
}
|
||||
@@ -441,6 +441,13 @@ class SearchEmailController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
void selectContactForSearchFilter(
|
||||
BuildContext context,
|
||||
PrefixEmailAddress prefixEmailAddress
|
||||
) async {
|
||||
|
||||
}
|
||||
|
||||
void _updateSimpleSearchFilter({
|
||||
Set<String>? from,
|
||||
SearchQuery? text,
|
||||
@@ -546,9 +553,7 @@ class SearchEmailController extends BaseController
|
||||
|
||||
void selectEmail(BuildContext context, PresentationEmail presentationEmailSelected) {
|
||||
listResultSearch.value = listResultSearch
|
||||
.map((email) => email.id == presentationEmailSelected.id
|
||||
? email.toggleSelect()
|
||||
: email)
|
||||
.map((email) => email.id == presentationEmailSelected.id ? email.toggleSelect() : email)
|
||||
.toList();
|
||||
|
||||
if (listResultSearch.isAllSelectionInActive) {
|
||||
|
||||
@@ -6,7 +6,6 @@ import 'package:core/presentation/utils/style_utils.dart';
|
||||
import 'package:core/presentation/views/background/background_widget_builder.dart';
|
||||
import 'package:core/presentation/views/button/icon_button_web.dart';
|
||||
import 'package:core/presentation/views/text/text_field_builder.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/build_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
@@ -163,8 +162,9 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
||||
child: ListView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
children: [
|
||||
_buildSearchFilterByContactButton(context, PrefixEmailAddress.from),
|
||||
_buildSearchFilterByContactButton(context, PrefixEmailAddress.to),
|
||||
...[
|
||||
QuickSearchFilter.fromMe,
|
||||
QuickSearchFilter.hasAttachment,
|
||||
QuickSearchFilter.last7Days
|
||||
].map((filter) => _buildQuickSearchFilterButton(context, filter)),
|
||||
@@ -177,7 +177,6 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
||||
Widget _buildQuickSearchFilterButton(BuildContext context, QuickSearchFilter filter) {
|
||||
return Obx(() {
|
||||
final filterSelected = controller.checkQuickSearchFilterSelected(filter);
|
||||
log('SearchEmailView::_buildQuickSearchFilterButton(): filterSelected: $filterSelected');
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: InkWell(
|
||||
@@ -237,9 +236,10 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
||||
... [
|
||||
const SizedBox(width: 4),
|
||||
SvgPicture.asset(
|
||||
_imagePaths.icChevronDown,
|
||||
width: 16,
|
||||
height: 16,
|
||||
_imagePaths.icChevronDownOutline,
|
||||
color: filterSelected
|
||||
? AppColor.primaryColor
|
||||
: AppColor.colorDefaultRichTextButton,
|
||||
fit: BoxFit.fill),
|
||||
]
|
||||
])
|
||||
@@ -253,7 +253,7 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
||||
BuildContext context,
|
||||
EmailReceiveTimeType? receiveTimeSelected,
|
||||
Function(EmailReceiveTimeType?)? onCallBack
|
||||
) {
|
||||
) {
|
||||
return EmailReceiveTimeType.values
|
||||
.map((timeType) => PopupMenuItem(
|
||||
padding: EdgeInsets.zero,
|
||||
@@ -553,10 +553,65 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
SvgPicture.asset(
|
||||
_imagePaths.icChevronDown,
|
||||
_imagePaths.icChevronDownOutline,
|
||||
color: filterSelected
|
||||
? AppColor.primaryColor
|
||||
: AppColor.colorDefaultRichTextButton,
|
||||
fit: BoxFit.fill),
|
||||
])
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildSearchFilterByContactButton(BuildContext context, PrefixEmailAddress prefixEmailAddress) {
|
||||
return Obx(() {
|
||||
final filterSelected = controller.simpleSearchFilter.value
|
||||
.searchFilterByContactApplied(prefixEmailAddress);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: InkWell(
|
||||
onTap: () => controller.selectContactForSearchFilter(context, prefixEmailAddress),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: filterSelected
|
||||
? AppColor.colorItemEmailSelectedDesktop
|
||||
: AppColor.colorButtonHeaderThread),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
SvgPicture.asset(
|
||||
filterSelected ? _imagePaths.icSelectedSB : _imagePaths.icUserSB,
|
||||
width: 16,
|
||||
height: 16,
|
||||
fit: BoxFit.fill),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
filterSelected
|
||||
? controller.simpleSearchFilter.value.getNameContactApplied(prefixEmailAddress)
|
||||
: controller.simpleSearchFilter.value.getNameContactDefault(context, prefixEmailAddress),
|
||||
maxLines: 1,
|
||||
overflow: CommonTextStyle.defaultTextOverFlow,
|
||||
softWrap: CommonTextStyle.defaultSoftWrap,
|
||||
style: filterSelected
|
||||
? const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColor.colorTextButton)
|
||||
: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: AppColor.colorTextButtonHeaderThread)
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
SvgPicture.asset(
|
||||
_imagePaths.icChevronDownOutline,
|
||||
color: filterSelected
|
||||
? AppColor.primaryColor
|
||||
: AppColor.colorDefaultRichTextButton,
|
||||
fit: BoxFit.fill),
|
||||
])
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user