TF-524 Drop down list recent search

This commit is contained in:
dab246
2022-05-23 20:23:39 +07:00
committed by Dat H. Pham
parent 51cc3bd979
commit 561ea8d1ad
13 changed files with 133 additions and 8 deletions
@@ -7,6 +7,7 @@ import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_cache.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_rights_cache.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_rights_cache.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/state_cache.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/state_cache.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/state_type.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/state_type.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/recent_search_cache.dart';
import 'package:tmail_ui_user/features/thread/data/model/email_address_hive_cache.dart'; import 'package:tmail_ui_user/features/thread/data/model/email_address_hive_cache.dart';
import 'package:tmail_ui_user/features/thread/data/model/email_cache.dart'; import 'package:tmail_ui_user/features/thread/data/model/email_cache.dart';
@@ -35,5 +36,6 @@ class HiveCacheConfig {
Hive.registerAdapter(StateTypeAdapter()); Hive.registerAdapter(StateTypeAdapter());
Hive.registerAdapter(EmailAddressHiveCacheAdapter()); Hive.registerAdapter(EmailAddressHiveCacheAdapter());
Hive.registerAdapter(EmailCacheAdapter()); Hive.registerAdapter(EmailCacheAdapter());
Hive.registerAdapter(RecentSearchCacheAdapter());
} }
} }
@@ -2,4 +2,6 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_sea
abstract class SearchDataSource { abstract class SearchDataSource {
Future<void> saveRecentSearch(RecentSearch recentSearch); Future<void> saveRecentSearch(RecentSearch recentSearch);
Future<List<RecentSearch>> getAllRecentSearchLatest({int? limit, String? pattern});
} }
@@ -2,6 +2,7 @@
import 'package:tmail_ui_user/features/caching/recent_search_cache_client.dart'; import 'package:tmail_ui_user/features/caching/recent_search_cache_client.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/search_datasource.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/search_datasource.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/recent_search_cache.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/model/recent_search_cache.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/extensions/list_recent_search_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart';
class SearchDataSourceImpl extends SearchDataSource { class SearchDataSourceImpl extends SearchDataSource {
@@ -26,4 +27,34 @@ class SearchDataSourceImpl extends SearchDataSource {
throw error; throw error;
}); });
} }
@override
Future<List<RecentSearch>> getAllRecentSearchLatest({int? limit, String? pattern}) {
return Future.sync(() async {
final listRecentSearchCache = await _recentSearchCacheClient.getAll();
final listRecentSearch = listRecentSearchCache
.where((recentCache) => _filterRecentSearchCache(recentCache, pattern))
.map((recentCache) => recentCache.toRecentSearch())
.toList();
listRecentSearch.sortByCreationDate();
final newLimit = limit ?? 10;
final newListRecentSearch = listRecentSearch.length > newLimit
? listRecentSearch.sublist(0, newLimit)
: listRecentSearch;
return newListRecentSearch;
}).catchError((error) {
throw error;
});
}
bool _filterRecentSearchCache(RecentSearchCache recentSearchCache, String? pattern) {
if (pattern == null || pattern.trim().isEmpty) {
return true;
} else {
return recentSearchCache.match(pattern);
}
}
} }
@@ -13,12 +13,12 @@ class RecentSearchCache extends HiveObject with EquatableMixin {
final String value; final String value;
@HiveField(1) @HiveField(1)
final DateTime creationTime; final DateTime creationDate;
RecentSearchCache(this.value, this.creationTime); RecentSearchCache(this.value, this.creationDate);
@override @override
List<Object?> get props => [value, creationTime]; List<Object?> get props => [value, creationDate];
} }
extension RecentSearchExtension on RecentSearch { extension RecentSearchExtension on RecentSearch {
@@ -26,3 +26,13 @@ extension RecentSearchExtension on RecentSearch {
return RecentSearchCache(value, creationDate); return RecentSearchCache(value, creationDate);
} }
} }
extension RecentSearchCacheExtension on RecentSearchCache {
RecentSearch toRecentSearch() {
return RecentSearch(value, creationDate);
}
bool match(String pattern) {
return value.toLowerCase().contains(pattern.toLowerCase());
}
}
@@ -13,4 +13,9 @@ class SearchRepositoryImpl extends SearchRepository {
Future<void> saveRecentSearch(RecentSearch recentSearch) { Future<void> saveRecentSearch(RecentSearch recentSearch) {
return searchDataSource.saveRecentSearch(recentSearch); return searchDataSource.saveRecentSearch(recentSearch);
} }
@override
Future<List<RecentSearch>> getAllRecentSearchLatest({int? limit, String? pattern}) {
return searchDataSource.getAllRecentSearchLatest(limit: limit, pattern: pattern);
}
} }
@@ -0,0 +1,12 @@
import 'package:jmap_dart_client/jmap/core/extensions/date_time_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart';
extension ListRecentSearchExtension on List<RecentSearch> {
void sortByCreationDate() {
sort((recentSearch1, recentSearch2) {
return recentSearch1.creationDate.compareToSort(recentSearch1.creationDate, false);
});
}
}
@@ -3,4 +3,6 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_sea
abstract class SearchRepository { abstract class SearchRepository {
Future<void> saveRecentSearch(RecentSearch recentSearch); Future<void> saveRecentSearch(RecentSearch recentSearch);
Future<List<RecentSearch>> getAllRecentSearchLatest({int? limit, String? pattern});
} }
@@ -0,0 +1,21 @@
import 'package:core/core.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart';
class GetAllRecentSearchLatestSuccess extends UIState {
final List<RecentSearch> listRecentSearch;
GetAllRecentSearchLatestSuccess(this.listRecentSearch);
@override
List<Object> get props => [listRecentSearch];
}
class GetAllRecentSearchLatestFailure extends FeatureFailure {
final dynamic exception;
GetAllRecentSearchLatestFailure(this.exception);
@override
List<Object> get props => [exception];
}
@@ -0,0 +1,22 @@
import 'dart:core';
import 'package:core/core.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/search_repository.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_recent_search_latest_state.dart';
class GetAllRecentSearchLatestInteractor {
final SearchRepository searchRepository;
GetAllRecentSearchLatestInteractor(this.searchRepository);
Future<Either<Failure, Success>> execute({int? limit, String? pattern}) async {
try {
final listRecent = await searchRepository.getAllRecentSearchLatest(limit: limit, pattern: pattern);
log('GetAllRecentSearchLatestInteractor::execute(): listRecent: ${listRecent.length}');
return Right(GetAllRecentSearchLatestSuccess(listRecent));
} catch (exception) {
return Left(GetAllRecentSearchLatestFailure(exception));
}
}
}
@@ -19,6 +19,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/search_
import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/search_datasource_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource_impl/search_datasource_impl.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/search_repository_impl.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/data/repository/search_repository_impl.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/search_repository.dart'; 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/get_user_profile_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/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/domain/usecases/save_recent_search_interactor.dart';
@@ -41,6 +42,7 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<MoveToMailboxInteractor>(), Get.find<MoveToMailboxInteractor>(),
Get.find<DeleteEmailPermanentlyInteractor>(), Get.find<DeleteEmailPermanentlyInteractor>(),
Get.find<SaveRecentSearchInteractor>(), Get.find<SaveRecentSearchInteractor>(),
Get.find<GetAllRecentSearchLatestInteractor>(),
)); ));
} }
@@ -68,6 +70,7 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.lazyPut(() => MoveToMailboxInteractor(Get.find<EmailRepository>())); Get.lazyPut(() => MoveToMailboxInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => DeleteEmailPermanentlyInteractor(Get.find<EmailRepository>())); Get.lazyPut(() => DeleteEmailPermanentlyInteractor(Get.find<EmailRepository>()));
Get.lazyPut(() => SaveRecentSearchInteractor(Get.find<SearchRepository>())); Get.lazyPut(() => SaveRecentSearchInteractor(Get.find<SearchRepository>()));
Get.lazyPut(() => GetAllRecentSearchLatestInteractor(Get.find<SearchRepository>()));
} }
@override @override
@@ -31,8 +31,10 @@ 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/domain/usecases/move_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart'; 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/get_user_profile_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/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/get_user_profile_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/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/domain/usecases/save_recent_search_interactor.dart';
@@ -61,6 +63,7 @@ class MailboxDashBoardController extends ReloadableController {
final MoveToMailboxInteractor _moveToMailboxInteractor; final MoveToMailboxInteractor _moveToMailboxInteractor;
final DeleteEmailPermanentlyInteractor _deleteEmailPermanentlyInteractor; final DeleteEmailPermanentlyInteractor _deleteEmailPermanentlyInteractor;
final SaveRecentSearchInteractor _saveRecentSearchInteractor; final SaveRecentSearchInteractor _saveRecentSearchInteractor;
final GetAllRecentSearchLatestInteractor _getAllRecentSearchLatestInteractor;
final scaffoldKey = GlobalKey<ScaffoldState>(); final scaffoldKey = GlobalKey<ScaffoldState>();
final selectedMailbox = Rxn<PresentationMailbox>(); final selectedMailbox = Rxn<PresentationMailbox>();
@@ -90,6 +93,7 @@ class MailboxDashBoardController extends ReloadableController {
this._moveToMailboxInteractor, this._moveToMailboxInteractor,
this._deleteEmailPermanentlyInteractor, this._deleteEmailPermanentlyInteractor,
this._saveRecentSearchInteractor, this._saveRecentSearchInteractor,
this._getAllRecentSearchLatestInteractor,
); );
@override @override
@@ -402,6 +406,15 @@ class MailboxDashBoardController extends ReloadableController {
consumeState(_saveRecentSearchInteractor.execute(recentSearch)); consumeState(_saveRecentSearchInteractor.execute(recentSearch));
} }
Future<List<RecentSearch>> getAllRecentSearchAction(String pattern) async {
return await _getAllRecentSearchLatestInteractor.execute(pattern: pattern)
.then((result) => result.fold(
(failure) => <RecentSearch>[],
(success) => success is GetAllRecentSearchLatestSuccess
? success.listRecentSearch
: <RecentSearch>[]));
}
void composeEmailAction() { void composeEmailAction() {
if (kIsWeb) { if (kIsWeb) {
if (dashBoardAction.value is! ComposeEmailAction) { if (dashBoardAction.value is! ComposeEmailAction) {
@@ -510,7 +510,7 @@ class MailboxDashBoardView extends GetWidget<MailboxDashBoardController> with Ne
color: AppColor.colorTextButtonHeaderThread, color: AppColor.colorTextButtonHeaderThread,
fontWeight: FontWeight.w500))), fontWeight: FontWeight.w500))),
getRecentCallback: (pattern) async { getRecentCallback: (pattern) async {
return []; return controller.getAllRecentSearchAction(pattern);
}, },
itemRecentBuilder: (context, recent) { itemRecentBuilder: (context, recent) {
return RecentSearchItemTileWidget(recent); return RecentSearchItemTileWidget(recent);
+6 -4
View File
@@ -16,23 +16,25 @@ void main() async {
await MainBindings().dependencies(); await MainBindings().dependencies();
await HiveCacheConfig().setUp(); await HiveCacheConfig().setUp();
await dotenv.load(fileName: 'env.file'); await dotenv.load(fileName: 'env.file');
runApp(TMailApp()); runApp(const TMailApp());
}); });
} }
class TMailApp extends StatelessWidget { class TMailApp extends StatelessWidget {
const TMailApp({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetMaterialApp( return GetMaterialApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
theme: appTheme(), theme: appTheme(),
supportedLocales: [ supportedLocales: const [
Locale('en'), Locale('en'),
Locale('vi'), Locale('vi'),
Locale('ru'), Locale('ru'),
Locale('fr') Locale('fr')
], ],
localizationsDelegates: [ localizationsDelegates: const [
AppLocalizationsDelegate(), AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate, GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate, GlobalWidgetsLocalizations.delegate,
@@ -46,7 +48,7 @@ class TMailApp extends StatelessWidget {
} }
return supportedLocales.first; return supportedLocales.first;
}, },
locale: Get.locale ?? Locale('en'), locale: Get.locale ?? const Locale('en'),
onGenerateTitle: (context) => AppLocalizations.of(context).page_name, onGenerateTitle: (context) => AppLocalizations.of(context).page_name,
defaultTransition: Transition.fade, defaultTransition: Transition.fade,
initialRoute: AppRoutes.HOME, initialRoute: AppRoutes.HOME,