diff --git a/lib/features/caching/caching_manager.dart b/lib/features/caching/caching_manager.dart index 0708ae0d7..71a34d4d6 100644 --- a/lib/features/caching/caching_manager.dart +++ b/lib/features/caching/caching_manager.dart @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:tmail_ui_user/features/caching/email_cache_client.dart'; import 'package:tmail_ui_user/features/caching/mailbox_cache_client.dart'; +import 'package:tmail_ui_user/features/caching/recent_search_cache_client.dart'; import 'package:tmail_ui_user/features/caching/state_cache_client.dart'; class CachingManager { @@ -9,11 +10,13 @@ class CachingManager { final MailboxCacheClient _mailboxCacheClient; final StateCacheClient _stateCacheClient; final EmailCacheClient _emailCacheClient; + final RecentSearchCacheClient _recentSearchCacheClient; CachingManager( this._mailboxCacheClient, this._stateCacheClient, - this._emailCacheClient + this._emailCacheClient, + this._recentSearchCacheClient, ); Future clearAll() async { @@ -22,12 +25,14 @@ class CachingManager { _stateCacheClient.clearAllData(), _mailboxCacheClient.clearAllData(), _emailCacheClient.clearAllData(), + _recentSearchCacheClient.clearAllData(), ]); } else { await Future.wait([ _stateCacheClient.deleteBox(), _mailboxCacheClient.deleteBox(), _emailCacheClient.deleteBox(), + _recentSearchCacheClient.deleteBox(), ]); } } diff --git a/lib/features/mailbox_dashboard/data/datasource/search_datasource.dart b/lib/features/mailbox_dashboard/data/datasource/search_datasource.dart new file mode 100644 index 000000000..ec66fb0c5 --- /dev/null +++ b/lib/features/mailbox_dashboard/data/datasource/search_datasource.dart @@ -0,0 +1,5 @@ +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart'; + +abstract class SearchDataSource { + Future saveRecentSearch(RecentSearch recentSearch); +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/data/datasource_impl/search_datasource_impl.dart b/lib/features/mailbox_dashboard/data/datasource_impl/search_datasource_impl.dart new file mode 100644 index 000000000..3dc4ff161 --- /dev/null +++ b/lib/features/mailbox_dashboard/data/datasource_impl/search_datasource_impl.dart @@ -0,0 +1,29 @@ + +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/model/recent_search_cache.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart'; + +class SearchDataSourceImpl extends SearchDataSource { + + final RecentSearchCacheClient _recentSearchCacheClient; + + SearchDataSourceImpl(this._recentSearchCacheClient); + + @override + Future saveRecentSearch(RecentSearch recentSearch) { + return Future.sync(() async { + if (await _recentSearchCacheClient.isExistItem(recentSearch.value)) { + await _recentSearchCacheClient.updateItem( + recentSearch.value, + recentSearch.toRecentSearchCache()); + } else { + await _recentSearchCacheClient.insertItem( + recentSearch.value, + recentSearch.toRecentSearchCache()); + } + }).catchError((error) { + throw error; + }); + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/data/model/recent_search_cache.dart b/lib/features/mailbox_dashboard/data/model/recent_search_cache.dart index dba8c07a7..676dc2935 100644 --- a/lib/features/mailbox_dashboard/data/model/recent_search_cache.dart +++ b/lib/features/mailbox_dashboard/data/model/recent_search_cache.dart @@ -2,6 +2,7 @@ import 'package:equatable/equatable.dart'; import 'package:hive/hive.dart'; import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart'; part 'recent_search_cache.g.dart'; @@ -18,4 +19,10 @@ class RecentSearchCache extends HiveObject with EquatableMixin { @override List get props => [value, creationTime]; +} + +extension RecentSearchExtension on RecentSearch { + RecentSearchCache toRecentSearchCache() { + return RecentSearchCache(value, creationDate); + } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/data/repository/search_repository_impl.dart b/lib/features/mailbox_dashboard/data/repository/search_repository_impl.dart new file mode 100644 index 000000000..a30c8bec3 --- /dev/null +++ b/lib/features/mailbox_dashboard/data/repository/search_repository_impl.dart @@ -0,0 +1,16 @@ + +import 'package:tmail_ui_user/features/mailbox_dashboard/data/datasource/search_datasource.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/search_repository.dart'; + +class SearchRepositoryImpl extends SearchRepository { + + final SearchDataSource searchDataSource; + + SearchRepositoryImpl(this.searchDataSource); + + @override + Future saveRecentSearch(RecentSearch recentSearch) { + return searchDataSource.saveRecentSearch(recentSearch); + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/repository/search_repository.dart b/lib/features/mailbox_dashboard/domain/repository/search_repository.dart new file mode 100644 index 000000000..4dac4a666 --- /dev/null +++ b/lib/features/mailbox_dashboard/domain/repository/search_repository.dart @@ -0,0 +1,6 @@ + +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart'; + +abstract class SearchRepository { + Future saveRecentSearch(RecentSearch recentSearch); +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/state/save_recent_search_state.dart b/lib/features/mailbox_dashboard/domain/state/save_recent_search_state.dart new file mode 100644 index 000000000..88a58ee0b --- /dev/null +++ b/lib/features/mailbox_dashboard/domain/state/save_recent_search_state.dart @@ -0,0 +1,18 @@ +import 'package:core/core.dart'; + +class SaveRecentSearchSuccess extends UIState { + + SaveRecentSearchSuccess(); + + @override + List get props => []; +} + +class SaveRecentSearchFailure extends FeatureFailure { + final dynamic exception; + + SaveRecentSearchFailure(this.exception); + + @override + List get props => [exception]; +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart new file mode 100644 index 000000000..2147c39fd --- /dev/null +++ b/lib/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart @@ -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/model/recent_search.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/repository/search_repository.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/save_recent_search_state.dart'; + +class SaveRecentSearchInteractor { + final SearchRepository searchRepository; + + SaveRecentSearchInteractor(this.searchRepository); + + Stream> execute(RecentSearch recentSearch) async* { + try { + await searchRepository.saveRecentSearch(recentSearch); + yield Right(SaveRecentSearchSuccess()); + } catch (exception) { + yield Left(SaveRecentSearchFailure(exception)); + } + } +} \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart index abd79acc9..95c05bb67 100644 --- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart +++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_bindings.dart @@ -1,6 +1,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/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,8 +15,13 @@ import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_int 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/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'; +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/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/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/presentation/thread_bindings.dart'; @@ -34,6 +40,7 @@ class MailboxDashBoardBindings extends BaseBindings { Get.put(MailboxDashBoardController( Get.find(), Get.find(), + Get.find(), )); } @@ -41,6 +48,7 @@ class MailboxDashBoardBindings extends BaseBindings { void bindingsDataSource() { Get.lazyPut(() => Get.find()); Get.lazyPut(() => Get.find()); + Get.lazyPut(() => Get.find()); } @override @@ -50,6 +58,7 @@ class MailboxDashBoardBindings extends BaseBindings { Get.find(), Get.find() )); + Get.lazyPut(() => SearchDataSourceImpl(Get.find())); } @override @@ -58,11 +67,13 @@ class MailboxDashBoardBindings extends BaseBindings { Get.lazyPut(() => RemoveEmailDraftsInteractor(Get.find())); Get.lazyPut(() => MoveToMailboxInteractor(Get.find())); Get.lazyPut(() => DeleteEmailPermanentlyInteractor(Get.find())); + Get.lazyPut(() => SaveRecentSearchInteractor(Get.find())); } @override void bindingsRepository() { Get.lazyPut(() => Get.find()); + Get.lazyPut(() => Get.find()); } @override @@ -71,5 +82,6 @@ class MailboxDashBoardBindings extends BaseBindings { Get.find(), Get.find() )); + Get.lazyPut(() => SearchRepositoryImpl(Get.find())); } } \ No newline at end of file diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart index e366e48f0..cde20c69e 100644 --- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart @@ -30,10 +30,12 @@ import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state. import 'package:tmail_ui_user/features/email/domain/usecases/delete_email_permanently_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/mailbox_dashboard/domain/model/recent_search.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/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/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/model/search_query.dart'; @@ -58,6 +60,7 @@ class MailboxDashBoardController extends ReloadableController { final MoveToMailboxInteractor _moveToMailboxInteractor; final DeleteEmailPermanentlyInteractor _deleteEmailPermanentlyInteractor; + final SaveRecentSearchInteractor _saveRecentSearchInteractor; final scaffoldKey = GlobalKey(); final selectedMailbox = Rxn(); @@ -86,6 +89,7 @@ class MailboxDashBoardController extends ReloadableController { MailboxDashBoardController( this._moveToMailboxInteractor, this._deleteEmailPermanentlyInteractor, + this._saveRecentSearchInteractor, ); @override @@ -394,6 +398,10 @@ class MailboxDashBoardController extends ReloadableController { return null; } + void saveRecentSearch(RecentSearch recentSearch) { + consumeState(_saveRecentSearchInteractor.execute(recentSearch)); + } + void composeEmailAction() { if (kIsWeb) { if (dashBoardAction.value is! ComposeEmailAction) { diff --git a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart index 3aae64f5a..b38bd7b4b 100644 --- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart +++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart @@ -420,6 +420,12 @@ class MailboxDashBoardView extends GetWidget with Ne autofocus: true, focusNode: controller.searchFocus, textInputAction: TextInputAction.done, + onSubmitted: (keyword) { + log('MailboxDashBoardView::_buildSearchForm(): onSubmitted: $keyword'); + if (keyword.trim().isNotEmpty) { + controller.saveRecentSearch(RecentSearch(keyword, DateTime.now())); + } + }, decoration: InputDecoration( border: InputBorder.none, focusedBorder: InputBorder.none, @@ -431,7 +437,13 @@ class MailboxDashBoardView extends GetWidget with Ne ), leftButton: buildIconWeb( icon: SvgPicture.asset(_imagePaths.icSearchBar, width: 16, height: 16, fit: BoxFit.fill), - onTap: () => {}), + onTap: () { + final keyword = controller.searchInputController.text; + log('MailboxDashBoardView::_buildSearchForm(): buttonClick: $keyword'); + if (keyword.trim().isNotEmpty) { + controller.saveRecentSearch(RecentSearch(keyword, DateTime.now())); + } + }), rightButton: buildIconWeb( icon: SvgPicture.asset(_imagePaths.icComposerClose, width: 18, height: 18, fit: BoxFit.fill), onTap: () { diff --git a/lib/main/bindings/local/local_bindings.dart b/lib/main/bindings/local/local_bindings.dart index 1978193d6..11cdced46 100644 --- a/lib/main/bindings/local/local_bindings.dart +++ b/lib/main/bindings/local/local_bindings.dart @@ -4,6 +4,7 @@ import 'package:get/get.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/caching/email_cache_client.dart'; import 'package:tmail_ui_user/features/caching/mailbox_cache_client.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/mailbox/data/local/mailbox_cache_manager.dart'; import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart'; @@ -26,9 +27,12 @@ class LocalBindings extends Bindings { Get.put(MailboxCacheManager(Get.find())); Get.put(EmailCacheClient()); Get.put(EmailCacheManager(Get.find())); + Get.put(RecentSearchCacheClient()); Get.put(CachingManager( Get.find(), Get.find(), - Get.find())); + Get.find(), + Get.find(), + )); } } \ No newline at end of file