diff --git a/assets/images/ic_quotas.svg b/assets/images/ic_quotas.svg
new file mode 100644
index 000000000..a8f961589
--- /dev/null
+++ b/assets/images/ic_quotas.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/ic_quotas_warning.svg b/assets/images/ic_quotas_warning.svg
new file mode 100644
index 000000000..6333c56e7
--- /dev/null
+++ b/assets/images/ic_quotas_warning.svg
@@ -0,0 +1,4 @@
+
diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart
index 9c3c51c01..c405daca6 100644
--- a/core/lib/presentation/extensions/color_extension.dart
+++ b/core/lib/presentation/extensions/color_extension.dart
@@ -163,6 +163,9 @@ extension AppColor on Color {
static const colorBackgroundContactTagItem = Color(0xFFDCE0E5);
static const colorDeleteContactIcon = Color(0xFFAEB7C2);
static const colorItemRecipientSelected = Color(0xFFDFEEFF);
+ static const colorBackgroundQuotasWarning = Color(0xFFFFC107);
+ static const colorTitleQuotasWarning = Color(0xFFF05C44);
+ static const colorProgressQuotasWarning = Color(0xFFFFA000);
static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart
index b1b7c91b4..2768f52b3 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -172,6 +172,8 @@ class ImagePaths {
String get icCancelSelection => _getImagePath('ic_cancel_selection.svg');
String get icSelectedRecipient => _getImagePath('ic_selected_recipient.svg');
String get icDeleteRecipient => _getImagePath('ic_delete_recipient.svg');
+ String get icQuotas => _getImagePath('ic_quotas.svg');
+ String get icQuotasWarning => _getImagePath('ic_quotas_warning.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart
index e82409d54..1f1232504 100644
--- a/lib/features/email/presentation/email_view.dart
+++ b/lib/features/email/presentation/email_view.dart
@@ -15,6 +15,7 @@ import 'package:tmail_ui_user/features/email/presentation/widgets/bottom_bar_mai
import 'package:tmail_ui_user/features/email/presentation/widgets/email_action_cupertino_action_sheet_action_builder.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/vacation_response_extension.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart';
+import 'package:tmail_ui_user/features/quotas/presentation/widget/quotas_warning_banner_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class EmailView extends GetWidget {
@@ -88,6 +89,7 @@ class EmailView extends GetWidget {
Widget _buildEmailView(BuildContext context, PresentationEmail email) {
return Column(children: [
_buildAppBar(context, email),
+ const QuotasWarningBannerWidget(),
_buildVacationNotificationMessage(context),
const Divider(color: AppColor.colorDividerHorizontal, height: 1),
Expanded(
diff --git a/lib/features/mailbox/presentation/mailbox_view.dart b/lib/features/mailbox/presentation/mailbox_view.dart
index a3a52c0e2..d2c55f4ce 100644
--- a/lib/features/mailbox/presentation/mailbox_view.dart
+++ b/lib/features/mailbox/presentation/mailbox_view.dart
@@ -13,6 +13,7 @@ import 'package:tmail_ui_user/features/mailbox/presentation/widgets/bottom_bar_s
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/user_information_widget_builder.dart';
+import 'package:tmail_ui_user/features/quotas/presentation/widget/quotas_footer_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_app_bar_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -84,7 +85,7 @@ class MailboxView extends GetWidget {
} else {
return const SizedBox.shrink();
}
- })
+ }),
]),
)
)
@@ -228,6 +229,7 @@ class MailboxView extends GetWidget {
Obx(() => controller.folderMailboxTree.value.root.childrenItems?.isNotEmpty ?? false
? _buildMailboxCategory(context, MailboxCategories.folders, controller.folderMailboxTree.value.root)
: const SizedBox.shrink()),
+ const QuotasFooterWidget(),
])
);
}
diff --git a/lib/features/mailbox/presentation/mailbox_view_web.dart b/lib/features/mailbox/presentation/mailbox_view_web.dart
index 19989bea3..2afad7c4c 100644
--- a/lib/features/mailbox/presentation/mailbox_view_web.dart
+++ b/lib/features/mailbox/presentation/mailbox_view_web.dart
@@ -17,6 +17,7 @@ import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_fold
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_search_tile_builder.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/widgets/user_information_widget_builder.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_list_dashboard_item.dart';
+import 'package:tmail_ui_user/features/quotas/presentation/widget/quotas_footer_widget.dart';
import 'package:tmail_ui_user/features/thread/presentation/widgets/search_app_bar_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/utils/app_config.dart';
@@ -72,6 +73,7 @@ class MailboxView extends GetWidget with AppLoaderMixin, Popu
})),
]),
)),
+ const QuotasFooterWidget(),
]),
)
);
diff --git a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart
index c3ec2e288..63d449966 100644
--- a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart
+++ b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart
@@ -71,6 +71,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart';
+import 'package:tmail_ui_user/features/quotas/presentation/quotas_bindings.dart';
import 'package:tmail_ui_user/features/search/domain/usecases/refresh_changes_search_email_interactor.dart';
import 'package:tmail_ui_user/features/search/presentation/search_email_bindings.dart';
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
@@ -100,6 +101,7 @@ class MailboxDashBoardBindings extends BaseBindings {
ThreadBindings().dependencies();
EmailBindings().dependencies();
SearchEmailBindings().dependencies();
+ QuotasBindings().dependencies();
}
@override
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 4af66a4cb..5e9731ef0 100644
--- a/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
+++ b/lib/features/mailbox_dashboard/presentation/mailbox_dashboard_view_web.dart
@@ -22,6 +22,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/se
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/top_bar_thread_selection.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/vacation_response_extension.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart';
+import 'package:tmail_ui_user/features/quotas/presentation/widget/quotas_warning_banner_widget.dart';
import 'package:tmail_ui_user/features/search/presentation/search_email_view.dart';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
@@ -111,6 +112,7 @@ class MailboxDashBoardView extends BaseMailboxDashBoardView {
SizedBox(child: MailboxView(), width: responsiveUtils.defaultSizeMenu),
Expanded(child: Column(children: [
_buildEmptyTrashButton(context),
+ const QuotasWarningBannerWidget(),
_buildVacationNotificationMessage(context),
_buildListButtonQuickSearchFilter(context),
_buildMarkAsMailboxReadLoading(context),
diff --git a/lib/features/manage_account/presentation/manage_account_dashboard_view.dart b/lib/features/manage_account/presentation/manage_account_dashboard_view.dart
index 4901426d4..b6146b55e 100644
--- a/lib/features/manage_account/presentation/manage_account_dashboard_view.dart
+++ b/lib/features/manage_account/presentation/manage_account_dashboard_view.dart
@@ -20,6 +20,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings
import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/profiles_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_view.dart';
+import 'package:tmail_ui_user/features/quotas/presentation/widget/quotas_warning_banner_widget.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -85,6 +86,7 @@ class ManageAccountDashBoardView extends GetWidget getQuotas(AccountId accountId);
+}
diff --git a/lib/features/quotas/data/datasource_impl/quotas_data_source_impl.dart b/lib/features/quotas/data/datasource_impl/quotas_data_source_impl.dart
new file mode 100644
index 000000000..438709ce2
--- /dev/null
+++ b/lib/features/quotas/data/datasource_impl/quotas_data_source_impl.dart
@@ -0,0 +1,21 @@
+import 'package:jmap_dart_client/jmap/account_id.dart';
+import 'package:tmail_ui_user/features/quotas/data/datasource/quotas_data_source.dart';
+import 'package:tmail_ui_user/features/quotas/data/network/quotas_api.dart';
+import 'package:tmail_ui_user/features/quotas/domain/model/quotas_response.dart';
+import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
+
+class QuotasDataSourceImpl extends QuotasDataSource{
+ final QuotasAPI _quotasAPI;
+ final ExceptionThrower _exceptionThrower;
+
+ QuotasDataSourceImpl(this._quotasAPI, this._exceptionThrower);
+
+ @override
+ Future getQuotas(AccountId accountId) {
+ return Future.sync(() async {
+ return await _quotasAPI.getQuotas(accountId);
+ }).catchError((error) {
+ _exceptionThrower.throwException(error);
+ });
+ }
+}
\ No newline at end of file
diff --git a/lib/features/quotas/data/network/quotas_api.dart b/lib/features/quotas/data/network/quotas_api.dart
new file mode 100644
index 000000000..d3b0262c3
--- /dev/null
+++ b/lib/features/quotas/data/network/quotas_api.dart
@@ -0,0 +1,39 @@
+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:jmap_dart_client/jmap/quotas/get/get_quota_method.dart';
+import 'package:jmap_dart_client/jmap/quotas/get/get_quota_response.dart';
+import 'package:tmail_ui_user/features/quotas/domain/model/exceptions/quotas_exception.dart';
+import 'package:tmail_ui_user/features/quotas/domain/model/quotas_response.dart';
+
+class QuotasAPI {
+ final HttpClient _httpClient;
+
+ QuotasAPI(this._httpClient);
+
+ Future getQuotas(AccountId accountId) async {
+ final requestBuilder =
+ JmapRequestBuilder(_httpClient, ProcessingInvocation());
+ final getQuotaMethod = GetQuotaMethod(accountId);
+ final getQuotaInvocation = requestBuilder.invocation(getQuotaMethod);
+ final response = await (requestBuilder
+ ..usings(getQuotaMethod.requiredCapabilities))
+ .build()
+ .execute();
+
+ final getQuotaResponse = response.parse(
+ getQuotaInvocation.methodCallId, GetQuotaResponse.deserialize);
+
+ if(getQuotaResponse != null) {
+ return QuotasResponse(
+ accountId: getQuotaResponse.accountId,
+ notFound: getQuotaResponse.notFound,
+ quotas: getQuotaResponse.list,
+ state: getQuotaResponse.state,
+ );
+ } else {
+ throw NotFoundQuotasException();
+ }
+
+ }
+}
diff --git a/lib/features/quotas/data/repository/quotas_repository_impl.dart b/lib/features/quotas/data/repository/quotas_repository_impl.dart
new file mode 100644
index 000000000..9a2636661
--- /dev/null
+++ b/lib/features/quotas/data/repository/quotas_repository_impl.dart
@@ -0,0 +1,15 @@
+import 'package:jmap_dart_client/jmap/account_id.dart';
+import 'package:tmail_ui_user/features/quotas/data/datasource/quotas_data_source.dart';
+import 'package:tmail_ui_user/features/quotas/domain/model/quotas_response.dart';
+import 'package:tmail_ui_user/features/quotas/domain/repository/quotas_repository.dart';
+
+class QuotasRepositoryImpl extends QuotasRepository {
+ final QuotasDataSource _dataSource;
+
+ QuotasRepositoryImpl(this._dataSource);
+
+ @override
+ Future getQuotas(AccountId accountId) {
+ return _dataSource.getQuotas(accountId);
+ }
+}
diff --git a/lib/features/quotas/domain/model/exceptions/quotas_exception.dart b/lib/features/quotas/domain/model/exceptions/quotas_exception.dart
new file mode 100644
index 000000000..914236be9
--- /dev/null
+++ b/lib/features/quotas/domain/model/exceptions/quotas_exception.dart
@@ -0,0 +1,3 @@
+class NotFoundQuotasException implements Exception {
+ NotFoundQuotasException();
+}
diff --git a/lib/features/quotas/domain/model/quotas_response.dart b/lib/features/quotas/domain/model/quotas_response.dart
new file mode 100644
index 000000000..7aa01e239
--- /dev/null
+++ b/lib/features/quotas/domain/model/quotas_response.dart
@@ -0,0 +1,30 @@
+import 'package:equatable/equatable.dart';
+import 'package:jmap_dart_client/jmap/account_id.dart';
+import 'package:jmap_dart_client/jmap/core/id.dart';
+import 'package:jmap_dart_client/jmap/core/state.dart';
+import 'package:jmap_dart_client/jmap/quotas/quota.dart';
+
+class QuotasResponse with EquatableMixin {
+ final AccountId accountId;
+ final State state;
+ final List quotas;
+ final List? notFound;
+
+ QuotasResponse({
+ required this.accountId,
+ required this.state,
+ required this.quotas,
+ this.notFound,
+ });
+
+ bool hasData() {
+ return quotas.isNotEmpty;
+ }
+
+ @override
+ List