TF-4171 Add datasource/repository/interactor for get all labels

This commit is contained in:
dab246
2025-11-25 00:11:16 +07:00
committed by Dat H. Pham
parent 4af0ee1086
commit f4302e06e8
15 changed files with 250 additions and 0 deletions
+9
View File
@@ -2,3 +2,12 @@ export 'package:labels/model/label.dart';
export 'package:labels/model/hex_color.dart';
export 'package:labels/utils/labels_constants.dart';
export 'package:labels/method/set/set_label_method.dart';
export 'package:labels/method/set/set_label_response.dart';
export 'package:labels/method/get/get_label_method.dart';
export 'package:labels/method/get/get_label_response.dart';
export 'package:labels/method/changes/changes_label_method.dart';
export 'package:labels/method/changes/changes_label_response.dart';
export 'package:labels/extensions/label_extension.dart';
@@ -0,0 +1,6 @@
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:labels/model/label.dart';
abstract class LabelDatasource {
Future<List<Label>> getAllLabels(AccountId accountId);
}
@@ -0,0 +1,22 @@
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:labels/model/label.dart';
import 'package:tmail_ui_user/features/labels/data/datasource/label_datasource.dart';
import 'package:tmail_ui_user/features/labels/data/network/label_api.dart';
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
class LabelDatasourceImpl extends LabelDatasource {
final LabelApi _labelApi;
final ExceptionThrower _exceptionThrower;
LabelDatasourceImpl(this._labelApi, this._exceptionThrower);
@override
Future<List<Label>> getAllLabels(AccountId accountId) {
return Future.sync(() async {
return await _labelApi.getAllLabels(accountId);
}).catchError((error, stackTrace) async {
await _exceptionThrower.throwException(error, stackTrace);
throw error;
});
}
}
@@ -0,0 +1,26 @@
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/jmap_request.dart';
import 'package:labels/labels.dart';
class LabelApi {
final HttpClient _httpClient;
LabelApi(this._httpClient);
Future<List<Label>> getAllLabels(AccountId accountId) async {
final builder = JmapRequestBuilder(_httpClient, ProcessingInvocation());
final method = GetLabelMethod(accountId);
final invocation = builder.invocation(method);
final result =
await (builder..usings(method.requiredCapabilities)).build().execute();
final response = result.parse<GetLabelResponse>(
invocation.methodCallId,
GetLabelResponse.deserialize,
);
return response?.list ?? [];
}
}
@@ -0,0 +1,15 @@
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:labels/model/label.dart';
import 'package:tmail_ui_user/features/labels/data/datasource/label_datasource.dart';
import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart';
class LabelRepositoryImpl extends LabelRepository {
final LabelDatasource _labelDatasource;
LabelRepositoryImpl(this._labelDatasource);
@override
Future<List<Label>> getAllLabels(AccountId accountId) {
return _labelDatasource.getAllLabels(accountId);
}
}
@@ -0,0 +1,6 @@
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:labels/model/label.dart';
abstract class LabelRepository {
Future<List<Label>> getAllLabels(AccountId accountId);
}
@@ -0,0 +1,18 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:labels/model/label.dart';
class GettingAllLabel extends LoadingState {}
class GetAllLabelSuccess extends UIState {
final List<Label> labels;
GetAllLabelSuccess(this.labels);
@override
List<Object> get props => [labels];
}
class GetAllLabelFailure extends FeatureFailure {
GetAllLabelFailure(dynamic exception) : super(exception: exception);
}
@@ -0,0 +1,22 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart';
import 'package:tmail_ui_user/features/labels/domain/state/get_all_label_state.dart';
class GetAllLabelInteractor {
final LabelRepository _labelRepository;
GetAllLabelInteractor(this._labelRepository);
Stream<Either<Failure, Success>> execute(AccountId accountId) async* {
try {
yield Right(GettingAllLabel());
final labels = await _labelRepository.getAllLabels(accountId);
yield Right(GetAllLabelSuccess(labels));
} catch (e) {
yield Left(GetAllLabelFailure(e));
}
}
}
@@ -0,0 +1,58 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:labels/model/label.dart';
import 'package:labels/utils/labels_constants.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/labels/domain/state/get_all_label_state.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
import 'package:tmail_ui_user/features/labels/presentation/label_interactor_bindings.dart';
import 'package:tmail_ui_user/main/error/capability_validator.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class LabelController extends BaseController {
final labels = <Label>[].obs;
GetAllLabelInteractor? _getAllLabelInteractor;
bool isLabelCapabilitySupported(Session session, AccountId accountId) {
return LabelsConstants.labelsCapability.isSupported(session, accountId);
}
void injectLabelsBindings() {
LabelInteractorBindings().dependencies();
_getAllLabelInteractor = getBinding<GetAllLabelInteractor>();
}
void getAllLabels(AccountId accountId) {
if (_getAllLabelInteractor == null) return;
consumeState(_getAllLabelInteractor!.execute(accountId));
}
@override
void handleSuccessViewState(Success success) {
if (success is GetAllLabelSuccess) {
labels.value = success.labels;
} else {
super.handleSuccessViewState(success);
}
}
@override
void handleFailureViewState(Failure failure) {
if (failure is GetAllLabelFailure) {
labels.value = [];
} else {
super.handleFailureViewState(failure);
}
}
@override
void onClose() {
_getAllLabelInteractor = null;
super.onClose();
}
}
@@ -0,0 +1,43 @@
import 'package:get/get.dart';
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:tmail_ui_user/features/base/interactors_bindings.dart';
import 'package:tmail_ui_user/features/labels/data/datasource/label_datasource.dart';
import 'package:tmail_ui_user/features/labels/data/datasource_impl/label_datasource_impl.dart';
import 'package:tmail_ui_user/features/labels/data/network/label_api.dart';
import 'package:tmail_ui_user/features/labels/data/repository/label_repository_impl.dart';
import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
class LabelInteractorBindings extends InteractorsBindings {
@override
void bindingsDataSource() {
Get.lazyPut<LabelDatasource>(() => Get.find<LabelDatasourceImpl>());
}
@override
void bindingsDataSourceImpl() {
Get.lazyPut(() => LabelApi(Get.find<HttpClient>()));
Get.lazyPut(
() => LabelDatasourceImpl(
Get.find<LabelApi>(),
Get.find<RemoteExceptionThrower>(),
),
);
}
@override
void bindingsInteractor() {
Get.lazyPut(() => GetAllLabelInteractor(Get.find<LabelRepository>()));
}
@override
void bindingsRepository() {
Get.lazyPut<LabelRepository>(() => Get.find<LabelRepositoryImpl>());
}
@override
void bindingsRepositoryImpl() {
Get.lazyPut(() => LabelRepositoryImpl(Get.find<LabelDatasource>()));
}
}
@@ -55,6 +55,7 @@ import 'package:tmail_ui_user/features/identity_creator/data/datasource_impl/loc
import 'package:tmail_ui_user/features/identity_creator/data/repository/identity_creator_repository_impl.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/repository/identity_creator_repository.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/labels/presentation/label_controller.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasource.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart';
@@ -207,6 +208,8 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<GetSpamReportStateInteractor>(),
Get.find<GetSpamMailboxCachedInteractor>()));
Get.put(LabelController());
Get.lazyPut(() => ComposerManager());
Get.put(MailboxDashBoardController(
@@ -84,6 +84,7 @@ import 'package:tmail_ui_user/features/home/domain/state/auto_sign_in_via_deep_l
import 'package:tmail_ui_user/features/home/domain/usecases/store_session_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/state/get_identity_cache_on_web_state.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/labels/presentation/label_controller.dart';
import 'package:tmail_ui_user/features/login/domain/exceptions/logout_exception.dart';
import 'package:tmail_ui_user/features/login/domain/state/get_authentication_info_state.dart';
import 'package:tmail_ui_user/features/login/domain/state/get_stored_oidc_configuration_state.dart';
@@ -233,6 +234,7 @@ class MailboxDashBoardController extends ReloadableController
final AppGridDashboardController appGridDashboardController = Get.find<AppGridDashboardController>();
final SpamReportController spamReportController = Get.find<SpamReportController>();
final NetworkConnectionController networkConnectionController = Get.find<NetworkConnectionController>();
final LabelController labelController = Get.find<LabelController>();
final ComposerManager composerManager = Get.find<ComposerManager>();
final getAuthenticationInfoInteractor =
Get.find<GetAuthenticationInfoInteractor>();
@@ -905,6 +907,14 @@ class MailboxDashBoardController extends ReloadableController
paywallController = PaywallController(
ownEmailAddress: ownEmailAddress.value,
);
final isLabelCapabilitySupported = labelController
.isLabelCapabilitySupported(session, currentAccountId);
if (isLabelCapabilitySupported) {
labelController.injectLabelsBindings();
labelController.getAllLabels(currentAccountId);
}
}
void _handleMailtoURL(MailtoArguments arguments) {
@@ -33,6 +33,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/unsubscribe_email_i
import 'package:tmail_ui_user/features/home/domain/usecases/get_session_interactor.dart';
import 'package:tmail_ui_user/features/home/domain/usecases/store_session_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/labels/presentation/label_controller.dart';
import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
@@ -148,6 +149,7 @@ const fallbackGenerators = {
MockSpec<DownloadController>(fallbackGenerators: fallbackGenerators),
MockSpec<AppGridDashboardController>(fallbackGenerators: fallbackGenerators),
MockSpec<SpamReportController>(fallbackGenerators: fallbackGenerators),
MockSpec<LabelController>(fallbackGenerators: fallbackGenerators),
MockSpec<NetworkConnectionController>(fallbackGenerators: fallbackGenerators),
MockSpec<QuickSearchEmailInteractor>(),
MockSpec<SaveRecentSearchInteractor>(),
@@ -241,6 +243,7 @@ void main() {
final downloadController = MockDownloadController();
final appGridDashboardController = MockAppGridDashboardController();
final spamReportController = MockSpamReportController();
final labelController = MockLabelController();
final networkConnectionController = MockNetworkConnectionController();
// mock search controller direct dependencies
@@ -322,6 +325,7 @@ void main() {
Get.put<DownloadController>(downloadController);
Get.put<AppGridDashboardController>(appGridDashboardController);
Get.put<SpamReportController>(spamReportController);
Get.put<LabelController>(labelController);
Get.put<NetworkConnectionController>(networkConnectionController);
Get.put<CachingManager>(cachingManager);
Get.put<LanguageCacheManager>(languageCacheManager);
@@ -33,6 +33,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/unsubscribe_email_i
import 'package:tmail_ui_user/features/home/domain/usecases/get_session_interactor.dart';
import 'package:tmail_ui_user/features/home/domain/usecases/store_session_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/labels/presentation/label_controller.dart';
import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
@@ -159,6 +160,7 @@ const fallbackGenerators = {
MockSpec<DownloadController>(fallbackGenerators: fallbackGenerators),
MockSpec<AppGridDashboardController>(fallbackGenerators: fallbackGenerators),
MockSpec<SpamReportController>(fallbackGenerators: fallbackGenerators),
MockSpec<LabelController>(fallbackGenerators: fallbackGenerators),
MockSpec<NetworkConnectionController>(fallbackGenerators: fallbackGenerators),
MockSpec<QuickSearchEmailInteractor>(),
MockSpec<SaveRecentSearchInteractor>(),
@@ -242,6 +244,7 @@ void main() {
final downloadController = MockDownloadController();
final appGridDashboardController = MockAppGridDashboardController();
final spamReportController = MockSpamReportController();
final labelController = MockLabelController();
final networkConnectionController = MockNetworkConnectionController();
final quickSearchEmailInteractor = MockQuickSearchEmailInteractor();
@@ -328,6 +331,7 @@ void main() {
Get.put<DownloadController>(downloadController);
Get.put<AppGridDashboardController>(appGridDashboardController);
Get.put<SpamReportController>(spamReportController);
Get.put<LabelController>(labelController);
Get.put<NetworkConnectionController>(networkConnectionController);
Get.put<CachingManager>(cachingManager);
Get.put<LanguageCacheManager>(languageCacheManager);
@@ -33,6 +33,7 @@ import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart
import 'package:tmail_ui_user/features/home/domain/usecases/get_session_interactor.dart';
import 'package:tmail_ui_user/features/home/domain/usecases/store_session_interactor.dart';
import 'package:tmail_ui_user/features/identity_creator/domain/usecase/get_identity_cache_on_web_interactor.dart';
import 'package:tmail_ui_user/features/labels/presentation/label_controller.dart';
import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
@@ -136,6 +137,7 @@ const fallbackGenerators = {
MockSpec<DownloadController>(fallbackGenerators: fallbackGenerators),
MockSpec<AppGridDashboardController>(fallbackGenerators: fallbackGenerators),
MockSpec<SpamReportController>(fallbackGenerators: fallbackGenerators),
MockSpec<LabelController>(fallbackGenerators: fallbackGenerators),
MockSpec<NetworkConnectionController>(fallbackGenerators: fallbackGenerators),
MockSpec<RemoveEmailDraftsInteractor>(),
MockSpec<MoveToMailboxInteractor>(),
@@ -203,6 +205,7 @@ void main() {
final MockDownloadController downloadController = MockDownloadController();
final MockAppGridDashboardController appGridDashboardController = MockAppGridDashboardController();
final MockSpamReportController spamReportController = MockSpamReportController();
final MockLabelController labelController = MockLabelController();
final MockNetworkConnectionController networkConnectionController = MockNetworkConnectionController();
final composerManager = MockComposerManager();
@@ -346,6 +349,7 @@ void main() {
Get.put<DownloadController>(downloadController);
Get.put<AppGridDashboardController>(appGridDashboardController);
Get.put<SpamReportController>(spamReportController);
Get.put<LabelController>(labelController);
Get.put<NetworkConnectionController>(networkConnectionController);
Get.put<GetSessionInteractor>(getSessionInteractor);
Get.put<GetAuthenticatedAccountInteractor>(getAuthenticatedAccountInteractor);