TF-933 Add contact From/To button to search filter
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4.37301 6.42334C4.13339 6.21796 3.77265 6.24571 3.56727 6.48532C3.36188 6.72494 3.38963 7.08568 3.62925 7.29107L7.62925 10.7196C7.84324 10.9031 8.15901 10.9031 8.37301 10.7196L12.373 7.29107C12.6126 7.08568 12.6404 6.72494 12.435 6.48532C12.2296 6.24571 11.8689 6.21796 11.6292 6.42334L8.00113 9.53316L4.37301 6.42334Z" fill="#99A2AD"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 450 B |
@@ -160,6 +160,7 @@ class ImagePaths {
|
|||||||
String get icClock => _getImagePath('ic_clock.svg');
|
String get icClock => _getImagePath('ic_clock.svg');
|
||||||
String get icCalendar => _getImagePath('ic_calendar.svg');
|
String get icCalendar => _getImagePath('ic_calendar.svg');
|
||||||
String get icAddEmailForward => _getImagePath('ic_add_email_forwards.svg');
|
String get icAddEmailForward => _getImagePath('ic_add_email_forwards.svg');
|
||||||
|
String get icChevronDownOutline => _getImagePath('ic_chevron_down_outline.svg');
|
||||||
|
|
||||||
String _getImagePath(String imageName) {
|
String _getImagePath(String imageName) {
|
||||||
return AssetsPaths.images + imageName;
|
return AssetsPaths.images + imageName;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
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.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/filter/filter_operator.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';
|
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: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/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/features/thread/domain/model/search_query.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
class SimpleSearchFilter with EquatableMixin {
|
class SimpleSearchFilter with EquatableMixin {
|
||||||
final Set<String> from;
|
final Set<String> from;
|
||||||
|
final Set<String> to;
|
||||||
final SearchQuery? text;
|
final SearchQuery? text;
|
||||||
final PresentationMailbox? mailbox;
|
final PresentationMailbox? mailbox;
|
||||||
final EmailReceiveTimeType emailReceiveTimeType;
|
final EmailReceiveTimeType emailReceiveTimeType;
|
||||||
@@ -18,17 +21,20 @@ class SimpleSearchFilter with EquatableMixin {
|
|||||||
|
|
||||||
SimpleSearchFilter({
|
SimpleSearchFilter({
|
||||||
Set<String>? from,
|
Set<String>? from,
|
||||||
|
Set<String>? to,
|
||||||
EmailReceiveTimeType? emailReceiveTimeType,
|
EmailReceiveTimeType? emailReceiveTimeType,
|
||||||
bool? hasAttachment,
|
bool? hasAttachment,
|
||||||
this.text,
|
this.text,
|
||||||
this.before,
|
this.before,
|
||||||
this.mailbox,
|
this.mailbox,
|
||||||
}) : from = from ?? <String>{},
|
}) : from = from ?? <String>{},
|
||||||
|
to = to ?? <String>{},
|
||||||
hasAttachment = hasAttachment ?? false,
|
hasAttachment = hasAttachment ?? false,
|
||||||
emailReceiveTimeType = emailReceiveTimeType ?? EmailReceiveTimeType.allTime;
|
emailReceiveTimeType = emailReceiveTimeType ?? EmailReceiveTimeType.allTime;
|
||||||
|
|
||||||
SimpleSearchFilter copyWith({
|
SimpleSearchFilter copyWith({
|
||||||
Set<String>? from,
|
Set<String>? from,
|
||||||
|
Set<String>? to,
|
||||||
SearchQuery? text,
|
SearchQuery? text,
|
||||||
PresentationMailbox? mailbox,
|
PresentationMailbox? mailbox,
|
||||||
EmailReceiveTimeType? emailReceiveTimeType,
|
EmailReceiveTimeType? emailReceiveTimeType,
|
||||||
@@ -37,6 +43,7 @@ class SimpleSearchFilter with EquatableMixin {
|
|||||||
}) {
|
}) {
|
||||||
return SimpleSearchFilter(
|
return SimpleSearchFilter(
|
||||||
from: from ?? this.from,
|
from: from ?? this.from,
|
||||||
|
to: to ?? this.to,
|
||||||
text: text ?? this.text,
|
text: text ?? this.text,
|
||||||
mailbox: mailbox ?? this.mailbox,
|
mailbox: mailbox ?? this.mailbox,
|
||||||
emailReceiveTimeType: emailReceiveTimeType ?? this.emailReceiveTimeType,
|
emailReceiveTimeType: emailReceiveTimeType ?? this.emailReceiveTimeType,
|
||||||
@@ -63,6 +70,10 @@ class SimpleSearchFilter with EquatableMixin {
|
|||||||
LogicFilterOperator(
|
LogicFilterOperator(
|
||||||
Operator.AND,
|
Operator.AND,
|
||||||
from.map((e) => EmailFilterCondition(from: e)).toSet()),
|
from.map((e) => EmailFilterCondition(from: e)).toSet()),
|
||||||
|
if (to.isNotEmpty)
|
||||||
|
LogicFilterOperator(
|
||||||
|
Operator.AND,
|
||||||
|
to.map((e) => EmailFilterCondition(to: e)).toSet()),
|
||||||
};
|
};
|
||||||
|
|
||||||
return listEmailCondition.isNotEmpty
|
return listEmailCondition.isNotEmpty
|
||||||
@@ -71,7 +82,7 @@ class SimpleSearchFilter with EquatableMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@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 {
|
extension SearchEmailFilterExtension on SimpleSearchFilter {
|
||||||
@@ -79,6 +90,7 @@ extension SearchEmailFilterExtension on SimpleSearchFilter {
|
|||||||
SimpleSearchFilter toSimpleSearchFilterByBefore({UTCDate? newBefore}) {
|
SimpleSearchFilter toSimpleSearchFilterByBefore({UTCDate? newBefore}) {
|
||||||
return SimpleSearchFilter(
|
return SimpleSearchFilter(
|
||||||
from: from,
|
from: from,
|
||||||
|
to: to,
|
||||||
text: text,
|
text: text,
|
||||||
mailbox: mailbox,
|
mailbox: mailbox,
|
||||||
emailReceiveTimeType: emailReceiveTimeType,
|
emailReceiveTimeType: emailReceiveTimeType,
|
||||||
@@ -100,5 +112,53 @@ extension SearchEmailFilterExtension on SimpleSearchFilter {
|
|||||||
|
|
||||||
bool get searchFilterByMailboxApplied => mailbox != null;
|
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 ?? '';
|
String get mailboxName => mailbox?.name?.name ?? '';
|
||||||
}
|
}
|
||||||
@@ -441,6 +441,13 @@ class SearchEmailController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void selectContactForSearchFilter(
|
||||||
|
BuildContext context,
|
||||||
|
PrefixEmailAddress prefixEmailAddress
|
||||||
|
) async {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void _updateSimpleSearchFilter({
|
void _updateSimpleSearchFilter({
|
||||||
Set<String>? from,
|
Set<String>? from,
|
||||||
SearchQuery? text,
|
SearchQuery? text,
|
||||||
@@ -546,9 +553,7 @@ class SearchEmailController extends BaseController
|
|||||||
|
|
||||||
void selectEmail(BuildContext context, PresentationEmail presentationEmailSelected) {
|
void selectEmail(BuildContext context, PresentationEmail presentationEmailSelected) {
|
||||||
listResultSearch.value = listResultSearch
|
listResultSearch.value = listResultSearch
|
||||||
.map((email) => email.id == presentationEmailSelected.id
|
.map((email) => email.id == presentationEmailSelected.id ? email.toggleSelect() : email)
|
||||||
? email.toggleSelect()
|
|
||||||
: email)
|
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (listResultSearch.isAllSelectionInActive) {
|
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/background/background_widget_builder.dart';
|
||||||
import 'package:core/presentation/views/button/icon_button_web.dart';
|
import 'package:core/presentation/views/button/icon_button_web.dart';
|
||||||
import 'package:core/presentation/views/text/text_field_builder.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:core/utils/build_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
@@ -163,8 +162,9 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
|||||||
child: ListView(
|
child: ListView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
children: [
|
children: [
|
||||||
|
_buildSearchFilterByContactButton(context, PrefixEmailAddress.from),
|
||||||
|
_buildSearchFilterByContactButton(context, PrefixEmailAddress.to),
|
||||||
...[
|
...[
|
||||||
QuickSearchFilter.fromMe,
|
|
||||||
QuickSearchFilter.hasAttachment,
|
QuickSearchFilter.hasAttachment,
|
||||||
QuickSearchFilter.last7Days
|
QuickSearchFilter.last7Days
|
||||||
].map((filter) => _buildQuickSearchFilterButton(context, filter)),
|
].map((filter) => _buildQuickSearchFilterButton(context, filter)),
|
||||||
@@ -177,7 +177,6 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
|||||||
Widget _buildQuickSearchFilterButton(BuildContext context, QuickSearchFilter filter) {
|
Widget _buildQuickSearchFilterButton(BuildContext context, QuickSearchFilter filter) {
|
||||||
return Obx(() {
|
return Obx(() {
|
||||||
final filterSelected = controller.checkQuickSearchFilterSelected(filter);
|
final filterSelected = controller.checkQuickSearchFilterSelected(filter);
|
||||||
log('SearchEmailView::_buildQuickSearchFilterButton(): filterSelected: $filterSelected');
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(right: 8),
|
padding: const EdgeInsets.only(right: 8),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
@@ -237,9 +236,10 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
|||||||
... [
|
... [
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
_imagePaths.icChevronDown,
|
_imagePaths.icChevronDownOutline,
|
||||||
width: 16,
|
color: filterSelected
|
||||||
height: 16,
|
? AppColor.primaryColor
|
||||||
|
: AppColor.colorDefaultRichTextButton,
|
||||||
fit: BoxFit.fill),
|
fit: BoxFit.fill),
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
@@ -253,7 +253,7 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
EmailReceiveTimeType? receiveTimeSelected,
|
EmailReceiveTimeType? receiveTimeSelected,
|
||||||
Function(EmailReceiveTimeType?)? onCallBack
|
Function(EmailReceiveTimeType?)? onCallBack
|
||||||
) {
|
) {
|
||||||
return EmailReceiveTimeType.values
|
return EmailReceiveTimeType.values
|
||||||
.map((timeType) => PopupMenuItem(
|
.map((timeType) => PopupMenuItem(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
@@ -553,10 +553,65 @@ class SearchEmailView extends GetWidget<SearchEmailController>
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
SvgPicture.asset(
|
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,
|
width: 16,
|
||||||
height: 16,
|
height: 16,
|
||||||
fit: BoxFit.fill),
|
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