diff --git a/assets/images/ic_storage.svg b/assets/images/ic_storage.svg
new file mode 100644
index 000000000..d6b9b758a
--- /dev/null
+++ b/assets/images/ic_storage.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/ic_warning.svg b/assets/images/ic_warning.svg
new file mode 100644
index 000000000..a80addc83
--- /dev/null
+++ b/assets/images/ic_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 fd70934ba..e99e62270 100644
--- a/core/lib/presentation/extensions/color_extension.dart
+++ b/core/lib/presentation/extensions/color_extension.dart
@@ -241,6 +241,7 @@ extension AppColor on Color {
static const m3Tertiary20 = Color(0xFF71767C);
static const m3Neutral70 = Color(0xFFAEAAAE);
static const m3Neutral90 = Color(0xFFE6E1E5);
+ static const m3Neutral40 = Color(0xFF605D62);
static const m3SysLightSecondaryBlue = Color(0xFF5C9CE6);
static const m3SysLight = Color(0xFF0157AD);
static const m3SysOutline = Color(0xFFAEAEC0);
@@ -279,6 +280,9 @@ extension AppColor on Color {
static const lightGreenBBF7D0 = Color(0xFFBBF7D0);
static const lightBlueEFF6FF = Color(0xFFEFF6FF);
static const lightBlueBFDBFE = Color(0xFFBFDBFE);
+ static const lightGrayF6FAFF = Color(0xFFF6FAFF);
+ static const lightGrayF7F6F9 = Color(0xFFF7F6F9);
+ static const blue25AEFE = Color(0xFF25AEFE);
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 24c417b89..edf946446 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -249,6 +249,8 @@ class ImagePaths {
String get icPremium => _getImagePath('ic_premium.svg');
String get icCloud => _getImagePath('ic_cloud.svg');
String get icNoRules => _getImagePath('ic_no_rules.svg');
+ String get icStorage => _getImagePath('ic_storage.svg');
+ String get icWarning => _getImagePath('ic_warning.svg');
String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
diff --git a/lib/features/manage_account/presentation/extensions/validate_setting_capability_supported_extension.dart b/lib/features/manage_account/presentation/extensions/validate_setting_capability_supported_extension.dart
new file mode 100644
index 000000000..fd4d5355a
--- /dev/null
+++ b/lib/features/manage_account/presentation/extensions/validate_setting_capability_supported_extension.dart
@@ -0,0 +1,17 @@
+import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/manage_account_dashboard_controller.dart';
+import 'package:tmail_ui_user/main/error/capability_validator.dart';
+
+extension ValidateSettingCapabilitySupportedExtension
+ on ManageAccountDashBoardController {
+ bool get isStorageCapabilitySupported {
+ if (accountId.value != null && sessionCurrent != null) {
+ return CapabilityIdentifier.jmapQuota.isSupported(
+ sessionCurrent!,
+ accountId.value!,
+ );
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart b/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart
index 130fe044c..10828442f 100644
--- a/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart
+++ b/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart
@@ -38,6 +38,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/model/manage_
import 'package:tmail_ui_user/features/manage_account/presentation/model/settings_page_level.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/notification/bindings/notification_binding.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/preferences/bindings/preferences_bindings.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/storage/storage_bindings.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_controller_bindings.dart';
import 'package:tmail_ui_user/main/error/capability_validator.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
@@ -213,6 +214,9 @@ class ManageAccountDashBoardController extends ReloadableController
case AccountMenuItem.notification:
NotificationBinding().dependencies();
break;
+ case AccountMenuItem.storage:
+ StorageBindings().dependencies();
+ break;
default:
break;
}
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 78a99b7a3..5fc4864f0 100644
--- a/lib/features/manage_account/presentation/manage_account_dashboard_view.dart
+++ b/lib/features/manage_account/presentation/manage_account_dashboard_view.dart
@@ -11,6 +11,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/na
import 'package:tmail_ui_user/features/manage_account/presentation/email_rules/email_rules_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/handle_profile_setting_action_type_click_extension.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/vacation_response_extension.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/extensions/validate_setting_capability_supported_extension.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/identities/identities_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/language_and_region/language_and_region_view.dart';
@@ -20,6 +21,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/menu/manage_a
import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings/settings_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/preferences/preferences_view.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/storage/storage_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart';
@@ -167,6 +169,12 @@ class ManageAccountDashBoardView extends GetWidget {
),
]);
}),
+ Obx(() {
+ if (controller.manageAccountDashboardController.isStorageCapabilitySupported) {
+ return Column(children: [
+ Divider(
+ color: AppColor.colorDividerHorizontal,
+ height: 1,
+ indent: SettingsUtils.getHorizontalPadding(
+ context,
+ controller.responsiveUtils,
+ ),
+ endIndent: SettingsUtils.getHorizontalPadding(
+ context,
+ controller.responsiveUtils,
+ ),
+ ),
+ SettingFirstLevelTileBuilder(
+ key: const ValueKey('setting_storage'),
+ AccountMenuItem.storage.getName(AppLocalizations.of(context)),
+ AccountMenuItem.storage.getIcon(controller.imagePaths),
+ subtitle: AppLocalizations.of(context).storageSettingExplanation,
+ () => controller.selectSettings(AccountMenuItem.storage),
+ ),
+ ]);
+ } else {
+ return const SizedBox.shrink();
+ }
+ }),
Obx(() {
if (controller.manageAccountDashboardController.isFcmCapabilitySupported && PlatformInfo.isMobile) {
return Column(children: [
diff --git a/lib/features/manage_account/presentation/menu/settings/settings_view.dart b/lib/features/manage_account/presentation/menu/settings/settings_view.dart
index b2c8d6774..2ffddefed 100644
--- a/lib/features/manage_account/presentation/menu/settings/settings_view.dart
+++ b/lib/features/manage_account/presentation/menu/settings/settings_view.dart
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/email_rules/email_rules_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/vacation_response_extension.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/extensions/validate_setting_capability_supported_extension.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/identities/identities_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/language_and_region/language_and_region_view.dart';
@@ -13,6 +14,7 @@ import 'package:tmail_ui_user/features/manage_account/presentation/model/account
import 'package:tmail_ui_user/features/manage_account/presentation/model/settings_page_level.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/notification/notification_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/preferences/preferences_view.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/storage/storage_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_view.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart';
@@ -137,6 +139,12 @@ class SettingsView extends GetWidget {
return MailboxVisibilityView();
case AccountMenuItem.notification:
return const NotificationView();
+ case AccountMenuItem.storage:
+ if (controller.manageAccountDashboardController.isStorageCapabilitySupported) {
+ return const StorageView();
+ } else {
+ return const SizedBox.shrink();
+ }
default:
return const SizedBox.shrink();
}
diff --git a/lib/features/manage_account/presentation/model/account_menu_item.dart b/lib/features/manage_account/presentation/model/account_menu_item.dart
index 2f08d8552..9ef9bd47f 100644
--- a/lib/features/manage_account/presentation/model/account_menu_item.dart
+++ b/lib/features/manage_account/presentation/model/account_menu_item.dart
@@ -12,6 +12,7 @@ enum AccountMenuItem {
mailboxVisibility,
notification,
contactSupport,
+ storage,
signOut,
none;
@@ -35,6 +36,8 @@ enum AccountMenuItem {
return imagePaths.icNotification;
case AccountMenuItem.contactSupport:
return imagePaths.icHelp;
+ case AccountMenuItem.storage:
+ return imagePaths.icStorage;
case AccountMenuItem.signOut:
return imagePaths.icSignOut;
case AccountMenuItem.none:
@@ -62,6 +65,8 @@ enum AccountMenuItem {
return appLocalizations.notification;
case AccountMenuItem.contactSupport:
return appLocalizations.contactSupport;
+ case AccountMenuItem.storage:
+ return appLocalizations.storageQuotas;
case AccountMenuItem.signOut:
return appLocalizations.sign_out;
case AccountMenuItem.none:
@@ -83,6 +88,8 @@ enum AccountMenuItem {
return appLocalizations.vacationSettingExplanation;
case AccountMenuItem.mailboxVisibility:
return appLocalizations.folderVisibilitySubtitle;
+ case AccountMenuItem.storage:
+ return appLocalizations.storageSettingExplanation;
default:
return '';
}
@@ -108,6 +115,8 @@ enum AccountMenuItem {
return 'notification';
case AccountMenuItem.contactSupport:
return 'contact-support';
+ case AccountMenuItem.storage:
+ return 'storage';
case AccountMenuItem.signOut:
return 'sign-out';
case AccountMenuItem.none:
diff --git a/lib/features/manage_account/presentation/storage/storage_bindings.dart b/lib/features/manage_account/presentation/storage/storage_bindings.dart
new file mode 100644
index 000000000..ca14ee73b
--- /dev/null
+++ b/lib/features/manage_account/presentation/storage/storage_bindings.dart
@@ -0,0 +1,12 @@
+import 'package:get/get.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/storage/storage_controller.dart';
+import 'package:tmail_ui_user/features/quotas/domain/use_case/get_quotas_interactor.dart';
+import 'package:tmail_ui_user/features/quotas/presentation/quotas_interactor_bindings.dart';
+
+class StorageBindings extends Bindings {
+ @override
+ void dependencies() {
+ QuotasInteractorBindings().dependencies();
+ Get.lazyPut(() => StorageController(Get.find()));
+ }
+}
diff --git a/lib/features/manage_account/presentation/storage/storage_controller.dart b/lib/features/manage_account/presentation/storage/storage_controller.dart
new file mode 100644
index 000000000..8d82f6ae2
--- /dev/null
+++ b/lib/features/manage_account/presentation/storage/storage_controller.dart
@@ -0,0 +1,67 @@
+import 'package:core/presentation/state/failure.dart';
+import 'package:core/presentation/state/success.dart';
+import 'package:dartz/dartz.dart';
+import 'package:get/get.dart';
+import 'package:jmap_dart_client/jmap/account_id.dart';
+import 'package:jmap_dart_client/jmap/quotas/quota.dart';
+import 'package:tmail_ui_user/features/base/base_controller.dart';
+import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/manage_account_dashboard_controller.dart';
+import 'package:tmail_ui_user/features/quotas/domain/extensions/list_quotas_extensions.dart';
+import 'package:tmail_ui_user/features/quotas/domain/state/get_quotas_state.dart';
+import 'package:tmail_ui_user/features/quotas/domain/use_case/get_quotas_interactor.dart';
+
+class StorageController extends BaseController {
+ final dashBoardController = Get.find();
+
+ final GetQuotasInteractor _getQuotasInteractor;
+
+ final octetsQuota = Rxn();
+
+ StorageController(this._getQuotasInteractor);
+
+ @override
+ void onReady() {
+ final accountId = dashBoardController.accountId.value;
+ if(accountId != null) {
+ _getQuotasAction(accountId);
+ } else {
+ consumeState(
+ Stream.value(
+ Left(GetQuotasFailure(NotFoundAccountIdException())),
+ ),
+ );
+ }
+ super.onReady();
+ }
+
+ void _getQuotasAction(AccountId accountId) {
+ consumeState(_getQuotasInteractor.execute(accountId));
+ }
+
+ void _handleGetQuotasSuccess(GetQuotasSuccess success) {
+ octetsQuota.value = success.quotas.octetsQuota;
+ }
+
+ void onUpgradeStorage() {
+
+ }
+
+ @override
+ void handleSuccessViewState(Success success) {
+ if (success is GetQuotasSuccess) {
+ _handleGetQuotasSuccess(success);
+ } else {
+ super.handleSuccessViewState(success);
+ }
+ }
+
+ @override
+ void handleFailureViewState(Failure failure) {
+ if (failure is GetQuotasFailure) {
+ octetsQuota.value = null;
+ } else {
+ super.handleFailureViewState(failure);
+ }
+ }
+}
diff --git a/lib/features/manage_account/presentation/storage/storage_view.dart b/lib/features/manage_account/presentation/storage/storage_view.dart
new file mode 100644
index 000000000..d9ecfb8dc
--- /dev/null
+++ b/lib/features/manage_account/presentation/storage/storage_view.dart
@@ -0,0 +1,107 @@
+import 'package:core/presentation/utils/theme_utils.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/base/setting_detail_view_builder.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings_utils.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/storage/storage_controller.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/storage/widgets/storage_progress_bar_widget.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/storage/widgets/upgrade_storage_widget.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/widgets/setting_explanation_widget.dart';
+import 'package:tmail_ui_user/features/manage_account/presentation/widgets/setting_header_widget.dart';
+import 'package:tmail_ui_user/features/quotas/domain/extensions/quota_extensions.dart';
+
+class StorageView extends GetWidget {
+ const StorageView({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ final responsiveUtils = controller.responsiveUtils;
+ final isMobile = responsiveUtils.isMobile(context);
+ final isDesktop = responsiveUtils.isDesktop(context);
+ final isWebDesktop = responsiveUtils.isWebDesktop(context);
+
+ return SettingDetailViewBuilder(
+ responsiveUtils: responsiveUtils,
+ child: Container(
+ color: SettingsUtils.getContentBackgroundColor(
+ context,
+ responsiveUtils,
+ ),
+ decoration: SettingsUtils.getBoxDecorationForContent(
+ context,
+ responsiveUtils,
+ ),
+ width: double.infinity,
+ padding: isDesktop
+ ? const EdgeInsets.symmetric(vertical: 30, horizontal: 22)
+ : null,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ if (isWebDesktop)
+ SettingHeaderWidget(
+ menuItem: AccountMenuItem.storage,
+ textStyle: ThemeUtils.textStyleInter600().copyWith(
+ color: Colors.black.withValues(alpha: 0.9),
+ ),
+ padding: EdgeInsets.zero,
+ )
+ else
+ const SettingExplanationWidget(
+ menuItem: AccountMenuItem.storage,
+ padding: EdgeInsetsDirectional.only(
+ start: 16,
+ end: 16,
+ bottom: 16,
+ ),
+ isCenter: true,
+ textAlign: TextAlign.center,
+ ),
+ Expanded(
+ child: Padding(
+ padding: _getPadding(isMobile: isMobile, isDesktop: isDesktop),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Obx(() {
+ final octetsQuota = controller.octetsQuota.value;
+ if (octetsQuota != null && octetsQuota.storageAvailable) {
+ return StorageProgressBarWidget(
+ imagePaths: controller.imagePaths,
+ quota: octetsQuota,
+ isMobile: isMobile,
+ );
+ } else {
+ return const SizedBox.shrink();
+ }
+ }),
+ UpgradeStorageWidget(
+ imagePaths: controller.imagePaths,
+ isMobile: isMobile,
+ onUpgradeStorageAction: controller.onUpgradeStorage,
+ )
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ EdgeInsetsGeometry _getPadding({
+ bool isMobile = false,
+ bool isDesktop = false,
+ }) {
+ if (isMobile) {
+ return const EdgeInsetsDirectional.only(top: 31, start: 24, end: 24);
+ } else if (isDesktop) {
+ return const EdgeInsetsDirectional.only(top: 37, start: 15);
+ } else {
+ return const EdgeInsetsDirectional.only(top: 31, start: 32, end: 32);
+ }
+ }
+}
diff --git a/lib/features/manage_account/presentation/storage/widgets/storage_progress_bar_widget.dart b/lib/features/manage_account/presentation/storage/widgets/storage_progress_bar_widget.dart
new file mode 100644
index 000000000..366130943
--- /dev/null
+++ b/lib/features/manage_account/presentation/storage/widgets/storage_progress_bar_widget.dart
@@ -0,0 +1,141 @@
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+import 'package:core/presentation/utils/theme_utils.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:jmap_dart_client/jmap/quotas/quota.dart';
+import 'package:tmail_ui_user/features/quotas/domain/extensions/quota_extensions.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+class StorageProgressBarWidget extends StatelessWidget {
+ final ImagePaths imagePaths;
+ final Quota quota;
+ final bool isMobile;
+
+ const StorageProgressBarWidget({
+ super.key,
+ required this.imagePaths,
+ required this.quota,
+ this.isMobile = false,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ final appLocalizations = AppLocalizations.of(context);
+
+ final logoStorageWidget = Container(
+ width: 64,
+ height: 64,
+ decoration: const BoxDecoration(
+ color: AppColor.lightGrayF6FAFF,
+ borderRadius: BorderRadius.all(Radius.circular(100)),
+ ),
+ alignment: Alignment.center,
+ child: SvgPicture.asset(
+ imagePaths.icCloud,
+ width: 30.72,
+ height: 30.72,
+ fit: BoxFit.fill,
+ ),
+ );
+
+ final infoStorageWidgets = [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ Text(
+ quota.usedStorageAsString,
+ style: ThemeUtils.textStyleInter600().copyWith(
+ color: AppColor.m3SurfaceBackground,
+ fontSize: 18.13,
+ height: 22.66 / 18.13,
+ letterSpacing: 0.0,
+ ),
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ ),
+ Expanded(
+ child: Row(
+ children: [
+ Expanded(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ horizontal: 8,
+ ),
+ child: Text(
+ appLocalizations.storageUsedMessage(
+ quota.hardLimitStorageAsString,
+ ),
+ style: ThemeUtils.textStyleInter500().copyWith(
+ color: AppColor.m3Tertiary20,
+ fontSize: 9.06,
+ height: 13.6 / 9.06,
+ letterSpacing: 0.08,
+ ),
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ ),
+ ),
+ ),
+ Text(
+ appLocalizations.storageAvailableMessage(
+ quota.quotaAvailableStorageAsString,
+ ),
+ style: ThemeUtils.textStyleInter600().copyWith(
+ color: AppColor.m3Tertiary20,
+ fontSize: 9.06,
+ height: 13.6 / 9.06,
+ letterSpacing: 0.08,
+ ),
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ Container(
+ padding: const EdgeInsets.only(top: 5),
+ width: double.infinity,
+ child: LinearProgressIndicator(
+ color: quota.getQuotasStateProgressBarColor(
+ fromSetting: true,
+ ),
+ minHeight: 4.53,
+ backgroundColor: AppColor.lightGrayF7F6F9,
+ borderRadius: const BorderRadius.all(
+ Radius.circular(13.03),
+ ),
+ value: quota.usedStoragePercent,
+ ),
+ ),
+ ];
+
+ return Container(
+ width: isMobile ? double.infinity : 439,
+ padding: const EdgeInsets.only(bottom: 16),
+ child: isMobile
+ ? Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ logoStorageWidget,
+ const SizedBox(height: 8),
+ ...infoStorageWidgets,
+ ],
+ )
+ : Row(
+ children: [
+ logoStorageWidget,
+ const SizedBox(width: 24),
+ Expanded(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: infoStorageWidgets,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/features/manage_account/presentation/storage/widgets/upgrade_storage_widget.dart b/lib/features/manage_account/presentation/storage/widgets/upgrade_storage_widget.dart
new file mode 100644
index 000000000..18f66e78e
--- /dev/null
+++ b/lib/features/manage_account/presentation/storage/widgets/upgrade_storage_widget.dart
@@ -0,0 +1,68 @@
+import 'package:core/presentation/extensions/color_extension.dart';
+import 'package:core/presentation/resources/image_paths.dart';
+import 'package:core/presentation/utils/theme_utils.dart';
+import 'package:core/presentation/views/dialog/confirm_dialog_button.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
+
+class UpgradeStorageWidget extends StatelessWidget {
+ final ImagePaths imagePaths;
+ final bool isMobile;
+ final VoidCallback onUpgradeStorageAction;
+
+ const UpgradeStorageWidget({
+ super.key,
+ required this.imagePaths,
+ required this.onUpgradeStorageAction,
+ this.isMobile = false,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ final appLocalizations = AppLocalizations.of(context);
+ return SizedBox(
+ width: isMobile ? double.infinity : 439,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SvgPicture.asset(
+ imagePaths.icWarning,
+ width: 16,
+ height: 16,
+ fit: BoxFit.fill,
+ ),
+ const SizedBox(width: 7),
+ Expanded(
+ child: Text(
+ appLocalizations.storageIsAlmostFullMessage,
+ style: ThemeUtils.textStyleInter600().copyWith(
+ color: AppColor.m3Neutral40,
+ fontSize: 12,
+ height: 16 / 12,
+ letterSpacing: 0.4,
+ ),
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(height: 16),
+ Container(
+ constraints: const BoxConstraints(minWidth: 179),
+ height: 48,
+ child: ConfirmDialogButton(
+ label: appLocalizations.upgradeStorage,
+ backgroundColor: AppColor.primaryMain,
+ textColor: Colors.white,
+ onTapAction: onUpgradeStorageAction,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/features/quotas/domain/extensions/quota_extensions.dart b/lib/features/quotas/domain/extensions/quota_extensions.dart
index 64828530f..457c76a1e 100644
--- a/lib/features/quotas/domain/extensions/quota_extensions.dart
+++ b/lib/features/quotas/domain/extensions/quota_extensions.dart
@@ -68,13 +68,13 @@ extension QuotasExtensions on Quota {
}
}
- Color getQuotasStateProgressBarColor() {
+ Color getQuotasStateProgressBarColor({bool fromSetting = false}) {
if (isHardLimitReached) {
return AppColor.colorQuotaError;
} else if (isWarnLimitReached) {
return AppColor.colorBackgroundQuotasWarning;
} else {
- return AppColor.blue400;
+ return fromSetting ? AppColor.blue25AEFE : AppColor.blue400;
}
}
diff --git a/lib/features/quotas/presentation/quotas_bindings.dart b/lib/features/quotas/presentation/quotas_bindings.dart
index ed57fd337..1868fc51b 100644
--- a/lib/features/quotas/presentation/quotas_bindings.dart
+++ b/lib/features/quotas/presentation/quotas_bindings.dart
@@ -1,43 +1,12 @@
import 'package:get/get.dart';
-import 'package:tmail_ui_user/features/base/base_bindings.dart';
-import 'package:tmail_ui_user/features/quotas/data/datasource/quotas_data_source.dart';
-import 'package:tmail_ui_user/features/quotas/data/datasource_impl/quotas_data_source_impl.dart';
-import 'package:tmail_ui_user/features/quotas/data/network/quotas_api.dart';
-import 'package:tmail_ui_user/features/quotas/data/repository/quotas_repository_impl.dart';
-import 'package:tmail_ui_user/features/quotas/domain/repository/quotas_repository.dart';
import 'package:tmail_ui_user/features/quotas/domain/use_case/get_quotas_interactor.dart';
import 'package:tmail_ui_user/features/quotas/presentation/quotas_controller.dart';
-import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
-
-class QuotasBindings extends BaseBindings {
+import 'package:tmail_ui_user/features/quotas/presentation/quotas_interactor_bindings.dart';
+class QuotasBindings extends Bindings {
@override
- void bindingsController() {
+ void dependencies() {
+ QuotasInteractorBindings().dependencies();
Get.put(QuotasController(Get.find()));
}
-
- @override
- void bindingsDataSource() {
- Get.lazyPut(() => (Get.find()));
- }
-
- @override
- void bindingsDataSourceImpl() {
- Get.lazyPut(() => QuotasDataSourceImpl(Get.find(), Get.find()));
- }
-
- @override
- void bindingsInteractor() {
- Get.lazyPut(() => GetQuotasInteractor(Get.find()));
- }
-
- @override
- void bindingsRepository() {
- Get.lazyPut(() => Get.find());
- }
-
- @override
- void bindingsRepositoryImpl() {
- Get.lazyPut(() => QuotasRepositoryImpl(Get.find()));
- }
}
\ No newline at end of file
diff --git a/lib/features/quotas/presentation/quotas_interactor_bindings.dart b/lib/features/quotas/presentation/quotas_interactor_bindings.dart
new file mode 100644
index 000000000..100b4f2ef
--- /dev/null
+++ b/lib/features/quotas/presentation/quotas_interactor_bindings.dart
@@ -0,0 +1,37 @@
+import 'package:get/get.dart';
+import 'package:tmail_ui_user/features/base/interactors_bindings.dart';
+import 'package:tmail_ui_user/features/quotas/data/datasource/quotas_data_source.dart';
+import 'package:tmail_ui_user/features/quotas/data/datasource_impl/quotas_data_source_impl.dart';
+import 'package:tmail_ui_user/features/quotas/data/network/quotas_api.dart';
+import 'package:tmail_ui_user/features/quotas/data/repository/quotas_repository_impl.dart';
+import 'package:tmail_ui_user/features/quotas/domain/repository/quotas_repository.dart';
+import 'package:tmail_ui_user/features/quotas/domain/use_case/get_quotas_interactor.dart';
+import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
+
+class QuotasInteractorBindings extends InteractorsBindings {
+
+ @override
+ void bindingsDataSource() {
+ Get.lazyPut(() => (Get.find()));
+ }
+
+ @override
+ void bindingsDataSourceImpl() {
+ Get.lazyPut(() => QuotasDataSourceImpl(Get.find(), Get.find()));
+ }
+
+ @override
+ void bindingsInteractor() {
+ Get.lazyPut(() => GetQuotasInteractor(Get.find()));
+ }
+
+ @override
+ void bindingsRepository() {
+ Get.lazyPut(() => Get.find());
+ }
+
+ @override
+ void bindingsRepositoryImpl() {
+ Get.lazyPut(() => QuotasRepositoryImpl(Get.find()));
+ }
+}
\ No newline at end of file
diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb
index 495fc749b..d3b1d4af4 100644
--- a/lib/l10n/intl_messages.arb
+++ b/lib/l10n/intl_messages.arb
@@ -4887,5 +4887,43 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
+ },
+ "storageSettingExplanation": "Monitor your available space.",
+ "@storageSettingExplanation": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
+ "storageIsAlmostFullMessage": "The storage is almost full. You can free up space by deleting unnecessary files or subscribe to get extra space.",
+ "@storageIsAlmostFullMessage": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
+ "upgradeStorage": "Upgrade storage",
+ "@upgradeStorage": {
+ "type": "text",
+ "placeholders_order": [],
+ "placeholders": {}
+ },
+ "storageUsedMessage": "of {limit} used",
+ "@storageUsedMessage": {
+ "type": "text",
+ "placeholders_order": [
+ "limit"
+ ],
+ "placeholders": {
+ "limit": {}
+ }
+ },
+ "storageAvailableMessage": "Available: {count}",
+ "@storageAvailableMessage": {
+ "type": "text",
+ "placeholders_order": [
+ "count"
+ ],
+ "placeholders": {
+ "count": {}
+ }
}
}
\ No newline at end of file
diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart
index ae9b189b0..fe4b835f5 100644
--- a/lib/main/localizations/app_localizations.dart
+++ b/lib/main/localizations/app_localizations.dart
@@ -5161,4 +5161,41 @@ class AppLocalizations {
name: 'defaultIdentitySetupSuccessful',
);
}
+
+ String get storageSettingExplanation {
+ return Intl.message(
+ 'Monitor your available space.',
+ name: 'storageSettingExplanation',
+ );
+ }
+
+ String get storageIsAlmostFullMessage {
+ return Intl.message(
+ 'The storage is almost full. You can free up space by deleting unnecessary files or subscribe to get extra space.',
+ name: 'storageIsAlmostFullMessage',
+ );
+ }
+
+ String get upgradeStorage {
+ return Intl.message(
+ 'Upgrade storage',
+ name: 'upgradeStorage',
+ );
+ }
+
+ String storageUsedMessage(String limit) {
+ return Intl.message(
+ 'of $limit used',
+ name: 'storageUsedMessage',
+ args: [limit],
+ );
+ }
+
+ String storageAvailableMessage(String count) {
+ return Intl.message(
+ 'Available: $count',
+ name: 'storageAvailableMessage',
+ args: [count],
+ );
+ }
}