TF-524 Implement quick search emails in selected mailbox by word

This commit is contained in:
dab246
2022-05-23 20:59:37 +07:00
committed by Dat H. Pham
parent 561ea8d1ad
commit 243ce444cd
8 changed files with 157 additions and 6 deletions
@@ -0,0 +1,21 @@
import 'package:core/core.dart';
import 'package:model/email/presentation_email.dart';
class QuickSearchEmailSuccess extends UIState {
final List<PresentationEmail> emailList;
QuickSearchEmailSuccess(this.emailList);
@override
List<Object> get props => [emailList];
}
class QuickSearchEmailFailure extends FeatureFailure {
final dynamic exception;
QuickSearchEmailFailure(this.exception);
@override
List<Object> get props => [exception];
}
@@ -0,0 +1,45 @@
import 'package:core/core.dart';
import 'package:model/model.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/filter/filter.dart';
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/quick_search_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart';
class QuickSearchEmailInteractor {
final ThreadRepository threadRepository;
QuickSearchEmailInteractor(this.threadRepository);
Future<Either<Failure, Success>> execute(
AccountId accountId,
{
UnsignedInt? limit,
Set<Comparator>? sort,
Filter? filter,
Properties? properties,
}
) async {
try {
final emailList = await threadRepository.searchEmails(
accountId,
limit: limit,
sort: sort,
filter: filter,
properties: properties);
final presentationEmailList = emailList
.map((email) => email.toPresentationEmail())
.toList();
return Right(QuickSearchEmailSuccess(presentationEmailList));
} catch (e) {
return Left(QuickSearchEmailFailure(e));
}
}
}
@@ -2,6 +2,7 @@ import 'package:core/core.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/base_bindings.dart';
import 'package:tmail_ui_user/features/caching/recent_search_cache_client.dart';
import 'package:tmail_ui_user/features/caching/state_cache_client.dart';
import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart';
import 'package:tmail_ui_user/features/email/data/datasource/html_datasource.dart';
import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasource_impl.dart';
@@ -14,6 +15,8 @@ import 'package:tmail_ui_user/features/email/domain/usecases/delete_email_perman
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/email_bindings.dart';
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/state_datasource_impl.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_bindings.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/search_datasource.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/search_datasource_impl.dart';
@@ -21,9 +24,17 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/search_
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/search_repository.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_user_profile_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
import 'package:tmail_ui_user/features/thread/data/datasource_impl/local_thread_datasource_impl.dart';
import 'package:tmail_ui_user/features/thread/data/datasource_impl/thread_datasource_impl.dart';
import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart';
import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
import 'package:tmail_ui_user/features/thread/data/repository/thread_repository_impl.dart';
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_bindings.dart';
class MailboxDashBoardBindings extends BaseBindings {
@@ -43,6 +54,7 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<DeleteEmailPermanentlyInteractor>(),
Get.find<SaveRecentSearchInteractor>(),
Get.find<GetAllRecentSearchLatestInteractor>(),
Get.find<QuickSearchEmailInteractor>(),
));
}
@@ -51,6 +63,8 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.lazyPut<EmailDataSource>(() => Get.find<EmailDataSourceImpl>());
Get.lazyPut<HtmlDataSource>(() => Get.find<HtmlDataSourceImpl>());
Get.lazyPut<SearchDataSource>(() => Get.find<SearchDataSourceImpl>());
Get.lazyPut<ThreadDataSource>(() => Get.find<ThreadDataSourceImpl>());
Get.lazyPut<StateDataSource>(() => Get.find<StateDataSourceImpl>());
}
@override
@@ -61,6 +75,9 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<DioClient>()
));
Get.lazyPut(() => SearchDataSourceImpl(Get.find<RecentSearchCacheClient>()));
Get.lazyPut(() => ThreadDataSourceImpl(Get.find<ThreadAPI>()));
Get.lazyPut(() => LocalThreadDataSourceImpl(Get.find<EmailCacheManager>()));
Get.lazyPut(() => StateDataSourceImpl(Get.find<StateCacheClient>()));
}
@override
@@ -71,12 +88,14 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.lazyPut(() => DeleteEmailPermanentlyInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => SaveRecentSearchInteractor(Get.find<SearchRepository>()));
Get.lazyPut(() => GetAllRecentSearchLatestInteractor(Get.find<SearchRepository>()));
Get.lazyPut(() => QuickSearchEmailInteractor(Get.find<ThreadRepository>()));
}
@override
void bindingsRepository() {
Get.lazyPut<EmailRepository>(() => Get.find<EmailRepositoryImpl>());
Get.lazyPut<SearchRepository>(() => Get.find<SearchRepositoryImpl>());
Get.lazyPut<ThreadRepository>(() => Get.find<ThreadRepositoryImpl>());
}
@override
@@ -86,5 +105,13 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<HtmlDataSource>()
));
Get.lazyPut(() => SearchRepositoryImpl(Get.find<SearchDataSource>()));
Get.lazyPut(() => ThreadRepositoryImpl(
{
DataSourceType.network: Get.find<ThreadDataSource>(),
DataSourceType.local: Get.find<LocalThreadDataSourceImpl>()
},
Get.find<StateDataSource>(),
Get.find<EmailDataSource>(),
));
}
}
@@ -12,6 +12,10 @@ import 'package:jmap_dart_client/jmap/core/capability/mail_capability.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_comparator.dart';
import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_comparator_property.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/model.dart';
import 'package:package_info_plus/package_info_plus.dart';
@@ -33,13 +37,16 @@ import 'package:tmail_ui_user/features/email/presentation/model/composer_argumen
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_recent_search_latest_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_user_profile_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/quick_search_email_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_user_profile_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/manage_account_arguments.dart';
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
import 'package:tmail_ui_user/features/thread/domain/state/search_email_state.dart';
import 'package:tmail_ui_user/features/thread/presentation/model/search_state.dart';
@@ -64,6 +71,7 @@ class MailboxDashBoardController extends ReloadableController {
final DeleteEmailPermanentlyInteractor _deleteEmailPermanentlyInteractor;
final SaveRecentSearchInteractor _saveRecentSearchInteractor;
final GetAllRecentSearchLatestInteractor _getAllRecentSearchLatestInteractor;
final QuickSearchEmailInteractor _quickSearchEmailInteractor;
final scaffoldKey = GlobalKey<ScaffoldState>();
final selectedMailbox = Rxn<PresentationMailbox>();
@@ -94,6 +102,7 @@ class MailboxDashBoardController extends ReloadableController {
this._deleteEmailPermanentlyInteractor,
this._saveRecentSearchInteractor,
this._getAllRecentSearchLatestInteractor,
this._quickSearchEmailInteractor,
);
@override
@@ -415,6 +424,25 @@ class MailboxDashBoardController extends ReloadableController {
: <RecentSearch>[]));
}
Future<List<PresentationEmail>> quickSearchEmailsAction(String pattern) async {
if (accountId.value != null && selectedMailbox.value != null) {
return await _quickSearchEmailInteractor.execute(
accountId.value!,
limit: UnsignedInt(5),
sort: <Comparator>{}
..add(EmailComparator(EmailComparatorProperty.receivedAt)
..setIsAscending(false)),
filter: EmailFilterCondition(
text: pattern,
inMailbox: selectedMailbox.value!.id),
properties: ThreadConstants.propertiesQuickSearch
).then((result) => result.fold(
(failure) => <PresentationEmail>[],
(success) => success is QuickSearchEmailSuccess ? success.emailList : <PresentationEmail>[]));
}
return <PresentationEmail>[];
}
void composeEmailAction() {
if (kIsWeb) {
if (dashBoardAction.value is! ComposeEmailAction) {
@@ -4,6 +4,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:get/get.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/base/mixin/network_connection_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_view_web.dart';
import 'package:tmail_ui_user/features/email/presentation/email_view.dart';
@@ -24,7 +25,7 @@ import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with NetworkConnectionMixin,
UserSettingPopupMenuMixin, FilterEmailPopupMenuMixin {
UserSettingPopupMenuMixin, FilterEmailPopupMenuMixin, AppLoaderMixin {
final _responsiveUtils = Get.find<ResponsiveUtils>();
final _imagePaths = Get.find<ImagePaths>();
@@ -425,6 +426,7 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with Ne
if (keyword.trim().isNotEmpty) {
controller.saveRecentSearch(RecentSearch(keyword, DateTime.now()));
}
controller.searchEmail(context, keyword);
},
decoration: InputDecoration(
border: InputBorder.none,
@@ -443,6 +445,7 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with Ne
if (keyword.trim().isNotEmpty) {
controller.saveRecentSearch(RecentSearch(keyword, DateTime.now()));
}
controller.searchEmail(context, keyword);
}),
rightButton: buildIconWeb(
icon: SvgPicture.asset(_imagePaths.icComposerClose, width: 18, height: 18, fit: BoxFit.fill),
@@ -508,20 +511,31 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with Ne
child: Text(AppLocalizations.of(context).recent,
style: const TextStyle(fontSize: 13.0,
color: AppColor.colorTextButtonHeaderThread,
fontWeight: FontWeight.w500))),
fontWeight: FontWeight.w500)
)
),
loadingBuilder: (context) => Padding(
padding: const EdgeInsets.only(bottom: 16),
child: loadingWidget,
),
getRecentCallback: (pattern) async {
return controller.getAllRecentSearchAction(pattern);
},
itemRecentBuilder: (context, recent) {
return RecentSearchItemTileWidget(recent);
},
onRecentSelected: (recent) {
controller.searchInputController.text = recent.value;
controller.searchEmail(context, recent.value);
},
suggestionsCallback: (pattern) async {
return [];
return controller.quickSearchEmailsAction(pattern);
},
itemBuilder: (context, email) {
return EmailQuickSearchItemTileWidget(email, controller.selectedMailbox.value);
},
onSuggestionSelected: (autoCompleteResult) async {
}),
)),
const SizedBox(width: 16),
@@ -23,7 +23,7 @@ class EmailQuickSearchItemTileWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -24,4 +24,16 @@ class ThreadConstants {
EmailProperty.keywords,
EmailProperty.mailboxIds,
});
static final propertiesQuickSearch = Properties({
EmailProperty.id,
EmailProperty.subject,
EmailProperty.from,
EmailProperty.to,
EmailProperty.keywords,
EmailProperty.receivedAt,
EmailProperty.sentAt,
EmailProperty.preview,
EmailProperty.hasAttachment,
});
}
@@ -396,7 +396,9 @@ class ThreadController extends BaseController {
_accountId!,
limit: limit,
sort: _sortOrder,
filter: EmailFilterCondition(text: searchQuery!.value),
filter: EmailFilterCondition(
text: searchQuery!.value,
inMailbox: _currentMailboxId),
properties: ThreadConstants.propertiesDefault,
));
}
@@ -844,7 +846,9 @@ class ThreadController extends BaseController {
_accountId!,
limit: ThreadConstants.defaultLimit,
sort: _sortOrder,
filter: EmailFilterCondition(text: searchQuery!.value),
filter: EmailFilterCondition(
text: searchQuery!.value,
inMailbox: _currentMailboxId),
properties: ThreadConstants.propertiesDefault,
));
}