From 6ed3df52a2a0a5f8c776b358424dc8590ef14676 Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 21 Sep 2021 15:22:54 +0700 Subject: [PATCH] TF-60 Add domain get device contact suggestion --- .../model/contact_suggestion_source.dart | 4 ++ .../domain/repository/contact_repository.dart | 7 ++++ ...state.dart => get_autocomplete_state.dart} | 8 ++-- .../get_device_contact_suggestions_state.dart | 21 ++++++++++ ....dart => get_autocomplete_interactor.dart} | 11 +++-- ...mplete_with_device_contact_interactor.dart | 41 +++++++++++++++++++ ...device_contact_suggestions_interactor.dart | 21 ++++++++++ model/lib/contact/contact.dart | 17 ++++++++ model/lib/contact/device_contact.dart | 10 +++++ model/lib/model.dart | 6 ++- pubspec.yaml | 6 +++ 11 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 lib/features/composer/domain/model/contact_suggestion_source.dart create mode 100644 lib/features/composer/domain/repository/contact_repository.dart rename lib/features/composer/domain/state/{search_email_address_state.dart => get_autocomplete_state.dart} (58%) create mode 100644 lib/features/composer/domain/state/get_device_contact_suggestions_state.dart rename lib/features/composer/domain/usecases/{search_email_address_interactor.dart => get_autocomplete_interactor.dart} (57%) create mode 100644 lib/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart create mode 100644 lib/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart create mode 100644 model/lib/contact/contact.dart create mode 100644 model/lib/contact/device_contact.dart diff --git a/lib/features/composer/domain/model/contact_suggestion_source.dart b/lib/features/composer/domain/model/contact_suggestion_source.dart new file mode 100644 index 000000000..7d047b8ea --- /dev/null +++ b/lib/features/composer/domain/model/contact_suggestion_source.dart @@ -0,0 +1,4 @@ + +enum ContactSuggestionSource { + all, localContact, deviceContact +} \ No newline at end of file diff --git a/lib/features/composer/domain/repository/contact_repository.dart b/lib/features/composer/domain/repository/contact_repository.dart new file mode 100644 index 000000000..eb4b7be64 --- /dev/null +++ b/lib/features/composer/domain/repository/contact_repository.dart @@ -0,0 +1,7 @@ + +import 'package:model/model.dart'; +import 'package:tmail_ui_user/features/composer/domain/model/auto_complete_pattern.dart'; + +abstract class ContactRepository { + Future> getContactSuggestions(AutoCompletePattern autoCompletePattern); +} \ No newline at end of file diff --git a/lib/features/composer/domain/state/search_email_address_state.dart b/lib/features/composer/domain/state/get_autocomplete_state.dart similarity index 58% rename from lib/features/composer/domain/state/search_email_address_state.dart rename to lib/features/composer/domain/state/get_autocomplete_state.dart index 838c59ab1..044cfeb1b 100644 --- a/lib/features/composer/domain/state/search_email_address_state.dart +++ b/lib/features/composer/domain/state/get_autocomplete_state.dart @@ -1,20 +1,20 @@ import 'package:core/core.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; -class SearchEmailAddressSuccess extends UIState { +class GetAutoCompleteSuccess extends UIState { final List listEmailAddress; - SearchEmailAddressSuccess(this.listEmailAddress); + GetAutoCompleteSuccess(this.listEmailAddress); @override List get props => [listEmailAddress]; } -class SearchEmailAddressFailure extends FeatureFailure { +class GetAutoCompleteFailure extends FeatureFailure { final exception; - SearchEmailAddressFailure(this.exception); + GetAutoCompleteFailure(this.exception); @override List get props => [exception]; 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 new file mode 100644 index 000000000..f59321e61 --- /dev/null +++ b/lib/features/composer/domain/state/get_device_contact_suggestions_state.dart @@ -0,0 +1,21 @@ + +import 'package:core/core.dart'; +import 'package:model/model.dart'; + +class GetDeviceContactSuggestionsSuccess extends UIState { + final List results; + + GetDeviceContactSuggestionsSuccess(this.results); + + @override + List get props => [results]; +} + +class GetDeviceContactSuggestionsFailure extends FeatureFailure { + final exception; + + GetDeviceContactSuggestionsFailure(this.exception); + + @override + List get props => [exception]; +} \ No newline at end of file diff --git a/lib/features/composer/domain/usecases/search_email_address_interactor.dart b/lib/features/composer/domain/usecases/get_autocomplete_interactor.dart similarity index 57% rename from lib/features/composer/domain/usecases/search_email_address_interactor.dart rename to lib/features/composer/domain/usecases/get_autocomplete_interactor.dart index 9a2ef250a..c8c8c74c6 100644 --- a/lib/features/composer/domain/usecases/search_email_address_interactor.dart +++ b/lib/features/composer/domain/usecases/get_autocomplete_interactor.dart @@ -2,20 +2,19 @@ import 'package:core/core.dart'; import 'package:dartz/dartz.dart'; import 'package:tmail_ui_user/features/composer/domain/model/auto_complete_pattern.dart'; import 'package:tmail_ui_user/features/composer/domain/repository/auto_complete_repository.dart'; -import 'package:tmail_ui_user/features/composer/domain/state/save_email_address_state.dart'; -import 'package:tmail_ui_user/features/composer/domain/state/search_email_address_state.dart'; +import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart'; -class SearchEmailAddressInteractor { +class GetAutoCompleteInteractor { final AutoCompleteRepository autoCompleteRepository; - SearchEmailAddressInteractor(this.autoCompleteRepository); + GetAutoCompleteInteractor(this.autoCompleteRepository); Future> execute(AutoCompletePattern autoCompletePattern) async { try { final listEmailAddress = await autoCompleteRepository.getAutoComplete(autoCompletePattern); - return Right(SearchEmailAddressSuccess(listEmailAddress)); + return Right(GetAutoCompleteSuccess(listEmailAddress)); } catch (e) { - return Left(SaveEmailAddressFailure(e)); + return Left(GetAutoCompleteFailure(e)); } } } \ No newline at end of file diff --git a/lib/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart b/lib/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart new file mode 100644 index 000000000..0cf17e25b --- /dev/null +++ b/lib/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart @@ -0,0 +1,41 @@ + +import 'package:core/core.dart'; +import 'package:dartz/dartz.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; +import 'package:model/model.dart'; +import 'package:tmail_ui_user/features/composer/domain/model/auto_complete_pattern.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_device_contact_suggestions_interactor.dart'; + +class GetAutoCompleteWithDeviceContactInteractor { + final GetAutoCompleteInteractor _getAutoCompleteInteractor; + final GetDeviceContactSuggestionsInteractor _getDeviceContactSuggestionsInteractor; + + GetAutoCompleteWithDeviceContactInteractor(this._getAutoCompleteInteractor, this._getDeviceContactSuggestionsInteractor); + + Future> execute(AutoCompletePattern autoCompletePattern) async { + try { + final resultExecutions = await Future.wait([ + _getAutoCompleteInteractor.execute(autoCompletePattern), + _getDeviceContactSuggestionsInteractor.execute(autoCompletePattern) + ]); + + final autoCompleteResults = resultExecutions.first.fold( + (failure) => [], + (success) => success is GetAutoCompleteSuccess ? success.listEmailAddress : []); + + resultExecutions.last.map((success) { + if (success is GetDeviceContactSuggestionsSuccess && success.results.isNotEmpty) { + autoCompleteResults.addAll(success.results.map((contact) => contact.toEmailAddress())); + } + } + ); + + return Right(GetAutoCompleteSuccess(autoCompleteResults)); + } catch (exception) { + return Left(GetAutoCompleteFailure(exception)); + } + } +} \ No newline at end of file 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 new file mode 100644 index 000000000..706b45bb4 --- /dev/null +++ b/lib/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart @@ -0,0 +1,21 @@ + +import 'package:core/core.dart'; +import 'package:dartz/dartz.dart'; +import 'package:tmail_ui_user/features/composer/domain/model/auto_complete_pattern.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'; + +class GetDeviceContactSuggestionsInteractor { + final ContactRepository _contactRepository; + + GetDeviceContactSuggestionsInteractor(this._contactRepository); + + Future> execute(AutoCompletePattern autoCompletePattern) async { + try { + final resultList = await _contactRepository.getContactSuggestions(autoCompletePattern); + return Right(GetDeviceContactSuggestionsSuccess(resultList)); + } catch (exception) { + return Left(GetDeviceContactSuggestionsFailure(exception)); + } + } +} \ No newline at end of file diff --git a/model/lib/contact/contact.dart b/model/lib/contact/contact.dart new file mode 100644 index 000000000..74c145e91 --- /dev/null +++ b/model/lib/contact/contact.dart @@ -0,0 +1,17 @@ + +import 'package:equatable/equatable.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; + +abstract class Contact with EquatableMixin { + final String displayName; + final String email; + + Contact(this.displayName, this.email); + + @override + List get props => [displayName, email]; +} + +extension ContactExtension on Contact { + EmailAddress toEmailAddress() => EmailAddress(displayName, email); +} \ No newline at end of file diff --git a/model/lib/contact/device_contact.dart b/model/lib/contact/device_contact.dart new file mode 100644 index 000000000..a11ad9be1 --- /dev/null +++ b/model/lib/contact/device_contact.dart @@ -0,0 +1,10 @@ + +import 'package:equatable/equatable.dart'; +import 'package:model/contact/contact.dart'; + +class DeviceContact extends Contact implements EquatableMixin { + DeviceContact(String displayName, String email) : super(displayName, email); + + @override + List get props => super.props; +} diff --git a/model/lib/model.dart b/model/lib/model.dart index cd2dea0a3..4ffca65f8 100644 --- a/model/lib/model.dart +++ b/model/lib/model.dart @@ -37,4 +37,8 @@ export 'extensions/keyword_identifier_extension.dart'; export 'extensions/presentation_mailbox_extension.dart'; // Download -export 'download/download_task_id.dart'; \ No newline at end of file +export 'download/download_task_id.dart'; + +// Contact +export 'contact/contact.dart'; +export 'contact/device_contact.dart'; \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 69b468d8b..880d8e92d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -113,6 +113,12 @@ dependencies: # share share: 2.0.4 + # flutter_contacts + contacts_service: + git: + url: git://github.com/linagora/flutter_contacts.git + ref: master + dev_dependencies: flutter_test: sdk: flutter