TF-524 Drop down list recent search
This commit is contained in:
@@ -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,16 +13,26 @@ 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 {
|
||||||
RecentSearchCache toRecentSearchCache() {
|
RecentSearchCache toRecentSearchCache() {
|
||||||
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];
|
||||||
|
}
|
||||||
+22
@@ -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
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user