diff --git a/lib/features/composer/domain/state/get_device_contact_suggestions_state.dart b/lib/features/composer/domain/state/get_device_contact_suggestions_state.dart index cbda3c4f6..d39d27c93 100644 --- a/lib/features/composer/domain/state/get_device_contact_suggestions_state.dart +++ b/lib/features/composer/domain/state/get_device_contact_suggestions_state.dart @@ -1,14 +1,14 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; -import 'package:model/contact/contact.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; class GetDeviceContactSuggestionsSuccess extends UIState { - final List results; + final List listEmailAddress; - GetDeviceContactSuggestionsSuccess(this.results); + GetDeviceContactSuggestionsSuccess(this.listEmailAddress); @override - List get props => [results]; + List get props => [listEmailAddress]; } class GetDeviceContactSuggestionsFailure extends FeatureFailure { diff --git a/lib/features/composer/domain/usecases/get_all_autocomplete_interactor.dart b/lib/features/composer/domain/usecases/get_all_autocomplete_interactor.dart index 1793ee283..2237c0ee8 100644 --- a/lib/features/composer/domain/usecases/get_all_autocomplete_interactor.dart +++ b/lib/features/composer/domain/usecases/get_all_autocomplete_interactor.dart @@ -1,10 +1,10 @@ import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/success.dart'; +import 'package:core/utils/app_logger.dart'; import 'package:dartz/dartz.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/autocomplete/auto_complete_pattern.dart'; -import 'package:model/contact/contact.dart'; import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/get_device_contact_suggestions_state.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; @@ -26,16 +26,25 @@ class GetAllAutoCompleteInteractor { _getDeviceContactSuggestionsInteractor.execute(autoCompletePattern) ]); - final autoCompleteResults = resultExecutions.first.fold( - (failure) => [], - (success) => success is GetAutoCompleteSuccess ? success.listEmailAddress : []); + final autoCompleteResults = List.empty(growable: true); - resultExecutions.last.map((success) { - if (success is GetDeviceContactSuggestionsSuccess && success.results.isNotEmpty) { - autoCompleteResults.addAll(success.results.map((contact) => contact.toEmailAddress())); - } - } + final listEmailAddressFromServer = resultExecutions[0].fold( + (failure) => [], + (success) => success is GetAutoCompleteSuccess + ? success.listEmailAddress + : [] ); + log('GetAllAutoCompleteInteractor::execute:listEmailAddressFromServerc: $listEmailAddressFromServer'); + autoCompleteResults.addAll(listEmailAddressFromServer); + + final listEmailAddressFromDevice = resultExecutions[1].fold( + (failure) => [], + (success) => success is GetDeviceContactSuggestionsSuccess + ? success.listEmailAddress + : [] + ); + log('GetAllAutoCompleteInteractor::execute:listEmailAddressFromDevice: $listEmailAddressFromDevice'); + autoCompleteResults.addAll(listEmailAddressFromDevice); return Right(GetAutoCompleteSuccess(autoCompleteResults)); } catch (exception) { diff --git a/lib/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart b/lib/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart index 1d0a3523c..bca99fc3f 100644 --- a/lib/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart +++ b/lib/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart @@ -1,7 +1,10 @@ -import 'package:core/core.dart'; +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:core/utils/app_logger.dart'; import 'package:dartz/dartz.dart'; import 'package:model/autocomplete/auto_complete_pattern.dart'; +import 'package:model/contact/contact.dart'; import 'package:tmail_ui_user/features/composer/domain/repository/contact_repository.dart'; import 'package:tmail_ui_user/features/composer/domain/state/get_device_contact_suggestions_state.dart'; @@ -13,7 +16,9 @@ class GetDeviceContactSuggestionsInteractor { Future> execute(AutoCompletePattern autoCompletePattern) async { try { final resultList = await _contactRepository.getContactSuggestions(autoCompletePattern); - return Right(GetDeviceContactSuggestionsSuccess(resultList)); + final listEmailAddress = resultList.map((contact) => contact.toEmailAddress()).toList(); + log('GetDeviceContactSuggestionsInteractor::execute:listEmailAddress: $listEmailAddress'); + return Right(GetDeviceContactSuggestionsSuccess(listEmailAddress)); } catch (exception) { return Left(GetDeviceContactSuggestionsFailure(exception)); } diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 7704ad885..ed56af677 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -38,11 +38,13 @@ import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_ import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_base64_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/get_device_contact_suggestions_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_drafts_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/download_image_as_base64_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_all_autocomplete_interactor.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart'; @@ -129,6 +131,7 @@ class ComposerController extends BaseController { GetAllAutoCompleteInteractor? _getAllAutoCompleteInteractor; GetAutoCompleteInteractor? _getAutoCompleteInteractor; + GetDeviceContactSuggestionsInteractor? _getDeviceContactSuggestionsInteractor; List listToEmailAddress = []; List listCcEmailAddress = []; @@ -1031,12 +1034,21 @@ class ComposerController extends BaseController { log('ComposerController::getAutoCompleteSuggestion(): $word | $_contactSuggestionSource'); _getAllAutoCompleteInteractor = getBinding(); _getAutoCompleteInteractor = getBinding(); + _getDeviceContactSuggestionsInteractor = getBinding(); final accountId = mailboxDashBoardController.accountId.value; if (_contactSuggestionSource == ContactSuggestionSource.all) { - if (_getAllAutoCompleteInteractor == null || _getAutoCompleteInteractor == null) { + if (_getAllAutoCompleteInteractor == null && _getDeviceContactSuggestionsInteractor == null) { return []; + } else if (_getDeviceContactSuggestionsInteractor != null) { + final listEmailAddress = await _getDeviceContactSuggestionsInteractor! + .execute(AutoCompletePattern(word: word, accountId: accountId)) + .then((value) => value.fold( + (failure) => [], + (success) => _getAutoCompleteSuccess(success, word) + )); + return listEmailAddress; } final listEmailAddress = await _getAllAutoCompleteInteractor! @@ -1076,6 +1088,20 @@ class ComposerController extends BaseController { } } return success.listEmailAddress; + } else if (success is GetDeviceContactSuggestionsSuccess) { + if (success.listEmailAddress.isEmpty == true && GetUtils.isEmail(word)) { + final unknownEmailAddress = EmailAddress(word, word); + return [unknownEmailAddress]; + } + if (GetUtils.isEmail(word)) { + bool isContainsTypedEmail = success.listEmailAddress.any((emailAddress) => emailAddress.email == word); + if (!isContainsTypedEmail) { + final unknownEmailAddress = EmailAddress(word, word); + success.listEmailAddress.insert(0, unknownEmailAddress); + return success.listEmailAddress; + } + } + return success.listEmailAddress; } else { return []; } diff --git a/lib/features/contact/presentation/contact_controller.dart b/lib/features/contact/presentation/contact_controller.dart index ff32beeeb..b1bccbd3b 100644 --- a/lib/features/contact/presentation/contact_controller.dart +++ b/lib/features/contact/presentation/contact_controller.dart @@ -13,8 +13,10 @@ import 'package:debounce_throttle/debounce_throttle.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart'; import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/get_device_contact_suggestions_state.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_all_autocomplete_interactor.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart'; import 'package:tmail_ui_user/features/contact/presentation/model/contact_arguments.dart'; import 'package:tmail_ui_user/features/contact/presentation/widgets/contact_suggestion_box_item.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; @@ -31,6 +33,7 @@ class ContactController extends BaseController { GetAllAutoCompleteInteractor? _getAllAutoCompleteInteractor; GetAutoCompleteInteractor? _getAutoCompleteInteractor; + GetDeviceContactSuggestionsInteractor? _getDeviceContactSuggestionsInteractor; final Debouncer _deBouncerTime = Debouncer(const Duration(milliseconds: 500), initialValue: ''); AccountId? _accountId; @@ -119,10 +122,21 @@ class ContactController extends BaseController { Future> _getAutoCompleteSuggestion(String query) async { _getAllAutoCompleteInteractor = getBinding(); _getAutoCompleteInteractor = getBinding(); + _getDeviceContactSuggestionsInteractor = getBinding(); if (_contactSuggestionSource == ContactSuggestionSource.all) { - if (_getAllAutoCompleteInteractor == null || _getAutoCompleteInteractor == null) { + if (_getAllAutoCompleteInteractor == null && _getDeviceContactSuggestionsInteractor == null) { return []; + } else if (_getDeviceContactSuggestionsInteractor != null) { + final listEmailAddress = await _getDeviceContactSuggestionsInteractor! + .execute(AutoCompletePattern(word: query, limit: 30, accountId: _accountId)) + .then((value) => value.fold( + (failure) => [], + (success) => success is GetDeviceContactSuggestionsSuccess + ? success.listEmailAddress + : [] + )); + return listEmailAddress; } final listEmailAddress = await _getAllAutoCompleteInteractor! diff --git a/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart index 835738824..8f9a0a951 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart @@ -10,8 +10,10 @@ import 'package:super_tag_editor/tag_editor.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart'; import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/get_device_contact_suggestions_state.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_all_autocomplete_interactor.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart'; import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; @@ -33,6 +35,7 @@ import 'package:tmail_ui_user/main/routes/route_navigation.dart'; class AdvancedFilterController extends BaseController { GetAllAutoCompleteInteractor? _getAllAutoCompleteInteractor; GetAutoCompleteInteractor? _getAutoCompleteInteractor; + GetDeviceContactSuggestionsInteractor? _getDeviceContactSuggestionsInteractor; final dateFilterSelectedFormAdvancedSearch = EmailReceiveTimeType.allTime.obs; final hasAttachment = false.obs; @@ -192,10 +195,21 @@ class AdvancedFilterController extends BaseController { log('AdvancedFilterController::getAutoCompleteSuggestion(): $word | $_contactSuggestionSource'); _getAllAutoCompleteInteractor = getBinding(); _getAutoCompleteInteractor = getBinding(); + _getDeviceContactSuggestionsInteractor = getBinding(); if (_contactSuggestionSource == ContactSuggestionSource.all) { - if (_getAllAutoCompleteInteractor == null || _getAutoCompleteInteractor == null) { + if (_getAllAutoCompleteInteractor == null && _getDeviceContactSuggestionsInteractor == null) { return []; + } else if (_getDeviceContactSuggestionsInteractor != null) { + final listEmailAddress = await _getDeviceContactSuggestionsInteractor! + .execute(AutoCompletePattern(word: word, accountId: _mailboxDashBoardController.accountId.value)) + .then((value) => value.fold( + (failure) => [], + (success) => success is GetDeviceContactSuggestionsSuccess + ? success.listEmailAddress + : [] + )); + return listEmailAddress; } final listEmailAddress = await _getAllAutoCompleteInteractor! diff --git a/lib/features/manage_account/presentation/forward/controller/forward_recipient_controller.dart b/lib/features/manage_account/presentation/forward/controller/forward_recipient_controller.dart index 5a0314167..61d44b157 100644 --- a/lib/features/manage_account/presentation/forward/controller/forward_recipient_controller.dart +++ b/lib/features/manage_account/presentation/forward/controller/forward_recipient_controller.dart @@ -9,8 +9,10 @@ import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/autocomplete/auto_complete_pattern.dart'; import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart'; import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/get_device_contact_suggestions_state.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_all_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; +import 'package:tmail_ui_user/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/contact_autocomplete_bindings.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/tmail_autocomplete_bindings.dart'; import 'package:tmail_ui_user/main/error/capability_validator.dart'; @@ -23,6 +25,7 @@ class ForwardRecipientController { GetAllAutoCompleteInteractor? _getAllAutoCompleteInteractor; GetAutoCompleteInteractor? _getAutoCompleteInteractor; + GetDeviceContactSuggestionsInteractor? _getDeviceContactSuggestionsInteractor; AccountId? _accountId; Session? _session; @@ -53,11 +56,21 @@ class ForwardRecipientController { log('ForwardRecipientController::getAutoCompleteSuggestion(): $word'); _getAllAutoCompleteInteractor = getBinding(); _getAutoCompleteInteractor = getBinding(); + _getDeviceContactSuggestionsInteractor = getBinding(); if (_contactSuggestionSource == ContactSuggestionSource.all) { - if (_getAllAutoCompleteInteractor == null || _getAutoCompleteInteractor == null) { - log('ForwardRecipientController::getAutoCompleteSuggestion(): _getAllAutoCompleteInteractor is NULL'); + if (_getAllAutoCompleteInteractor == null && _getDeviceContactSuggestionsInteractor == null) { return []; + } else if (_getDeviceContactSuggestionsInteractor != null) { + final listEmailAddress = await _getDeviceContactSuggestionsInteractor! + .execute(AutoCompletePattern(word: word, accountId: _accountId)) + .then((value) => value.fold( + (failure) => [], + (success) => success is GetDeviceContactSuggestionsSuccess + ? success.listEmailAddress + : [] + )); + return listEmailAddress; } else { return await _getAllAutoCompleteInteractor! .execute(AutoCompletePattern(word: word, accountId: _accountId))