diff --git a/core/lib/utils/double_convert.dart b/core/lib/utils/double_convert.dart new file mode 100644 index 000000000..c1761e528 --- /dev/null +++ b/core/lib/utils/double_convert.dart @@ -0,0 +1,7 @@ +import 'dart:math'; + +class DoubleConvert { + static double bytesToGigaBytes(num bytes) { + return double.tryParse((bytes * 9.31 * pow(10, -10)).toStringAsFixed(2)) ?? 0; + } +} diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 9ec590f7a..34a5dd1e7 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -80,7 +80,7 @@ class MailboxController extends BaseMailboxController { final _imagePaths = Get.find(); final _responsiveUtils = Get.find(); final _uuid = Get.find(); - + final isMailboxListScrollable = false.obs; final GetAllMailboxInteractor _getAllMailboxInteractor; final RefreshAllMailboxInteractor _refreshAllMailboxInteractor; final CreateNewMailboxInteractor _createNewMailboxInteractor; @@ -200,6 +200,10 @@ class MailboxController extends BaseMailboxController { ); } + void handleScrollEnable() { + isMailboxListScrollable.value = mailboxListScrollController.hasClients && mailboxListScrollController.position.maxScrollExtent > 0; + } + void _registerListenerWorker() { accountIdWorker = ever(mailboxDashBoardController.accountId, (accountId) { if (accountId is AccountId) { diff --git a/lib/features/mailbox/presentation/mailbox_view.dart b/lib/features/mailbox/presentation/mailbox_view.dart index 38f6d9734..d6bb2d89e 100644 --- a/lib/features/mailbox/presentation/mailbox_view.dart +++ b/lib/features/mailbox/presentation/mailbox_view.dart @@ -44,56 +44,56 @@ class MailboxView extends GetWidget { body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column(children: [ - _buildHeaderMailbox(context), - Obx(() => controller.isSearchActive() - ? SafeArea(bottom: false, top: false, right: false, - child: _buildInputSearchFormWidget(context)) - : const SizedBox.shrink()), - Expanded(child: Obx(() => Container( - color: controller.isSearchActive() - ? Colors.white - : AppColor.colorBgMailbox, - child: RefreshIndicator( - color: AppColor.primaryColor, - onRefresh: () async => controller.refreshAllMailbox(), - child: SafeArea(top: false, right: false, - bottom: !controller.isSelectionEnabled(), - child: controller.isSearchActive() - ? _buildListMailboxSearched(context) - : Padding( - padding: EdgeInsets.only( - bottom: _responsiveUtils.isLandscapeMobile(context) - || controller.isSelectionEnabled() ? 0 : 24), - child: _buildListMailbox(context)) - ) - ), - ))), - Obx(() => controller.isSelectionEnabled() - ? _buildOptionSelectionMailbox(context) - : const SizedBox.shrink()), - ]), - ), - Obx(() => controller.isSelectionEnabled() - ? const SizedBox.shrink() - : const QuotasFooterWidget(padding: EdgeInsets.only(left: 24, right: 24, bottom: 8)), - ), - Obx(() { - final appInformation = controller.mailboxDashBoardController.appInformation.value; - if (appInformation != null - && !controller.isSearchActive() - && !controller.isSelectionEnabled()) { - if (_responsiveUtils.isLandscapeMobile(context)) { - return const SizedBox.shrink(); - } - return Align( - alignment: Alignment.bottomCenter, - child: _buildVersionInformation(context, appInformation)); - } else { - return const SizedBox.shrink(); - } - }) + Expanded( + child: Column(children: [ + _buildHeaderMailbox(context), + Obx(() => controller.isSearchActive() + ? SafeArea(bottom: false, top: false, right: false, + child: _buildInputSearchFormWidget(context)) + : const SizedBox.shrink()), + Expanded(child: Obx(() => Container( + color: controller.isSearchActive() + ? Colors.white + : AppColor.colorBgMailbox, + child: RefreshIndicator( + color: AppColor.primaryColor, + onRefresh: () async => controller.refreshAllMailbox(), + child: SafeArea(top: false, right: false, + bottom: !controller.isSelectionEnabled(), + child: controller.isSearchActive() + ? _buildListMailboxSearched(context) + : Padding( + padding: EdgeInsets.only( + bottom: _responsiveUtils.isLandscapeMobile(context) + || controller.isSelectionEnabled() ? 0 : 24), + child: _buildListMailbox(context)) + ) + ), + ))), + Obx(() => controller.isSelectionEnabled() + ? _buildOptionSelectionMailbox(context) + : const SizedBox.shrink()), + ]), + ), + Obx(() => controller.isMailboxListScrollable.isTrue && !controller.isSelectionEnabled() + ? const QuotasFooterWidget(padding: EdgeInsets.only(left: 24, right: 24, bottom: 8)) + : const SizedBox.shrink(), + ), + Obx(() { + final appInformation = controller.mailboxDashBoardController.appInformation.value; + if (appInformation != null + && !controller.isSearchActive() + && !controller.isSelectionEnabled()) { + if (_responsiveUtils.isLandscapeMobile(context)) { + return const SizedBox.shrink(); + } + return Align( + alignment: Alignment.bottomCenter, + child: _buildVersionInformation(context, appInformation)); + } else { + return const SizedBox.shrink(); + } + }) ]), ) ) @@ -216,28 +216,38 @@ class MailboxView extends GetWidget { } Widget _buildListMailbox(BuildContext context) { - return SingleChildScrollView( - controller: controller.mailboxListScrollController, - key: const PageStorageKey('mailbox_list'), - physics: const ClampingScrollPhysics(), - padding: EdgeInsets.only(bottom: controller.isSelectionEnabled() ? 16 : 0), - child: Column(children: [ - Obx(() { - if (controller.isSelectionEnabled() && _responsiveUtils.isLandscapeMobile(context)) { - return const SizedBox.shrink(); - } - return _buildUserInformation(context); - }), - _buildSearchBarWidget(context), - _buildLoadingView(), - Obx(() => controller.defaultMailboxTree.value.root.childrenItems?.isNotEmpty ?? false - ? _buildMailboxCategory(context, MailboxCategories.exchange, controller.defaultMailboxTree.value.root) - : const SizedBox.shrink()), - const SizedBox(height: 12), - Obx(() => controller.folderMailboxTree.value.root.childrenItems?.isNotEmpty ?? false - ? _buildMailboxCategory(context, MailboxCategories.folders, controller.folderMailboxTree.value.root) - : const SizedBox.shrink()), - ]) + return NotificationListener( + onNotification: (_) { + controller.handleScrollEnable(); + return true; + }, + child: SingleChildScrollView( + controller: controller.mailboxListScrollController, + key: const PageStorageKey('mailbox_list'), + physics: const ClampingScrollPhysics(), + padding: EdgeInsets.only(bottom: controller.isSelectionEnabled() ? 16 : 0), + child: Column(children: [ + Obx(() { + if (controller.isSelectionEnabled() && _responsiveUtils.isLandscapeMobile(context)) { + return const SizedBox.shrink(); + } + return _buildUserInformation(context); + }), + _buildSearchBarWidget(context), + _buildLoadingView(), + Obx(() => controller.defaultMailboxTree.value.root.childrenItems?.isNotEmpty ?? false + ? _buildMailboxCategory(context, MailboxCategories.exchange, controller.defaultMailboxTree.value.root) + : const SizedBox.shrink()), + const SizedBox(height: 12), + Obx(() => controller.folderMailboxTree.value.root.childrenItems?.isNotEmpty ?? false + ? _buildMailboxCategory(context, MailboxCategories.folders, controller.folderMailboxTree.value.root) + : const SizedBox.shrink()), + Obx(() => controller.isMailboxListScrollable.isFalse && !controller.isSelectionEnabled() + ? const QuotasFooterWidget(padding: EdgeInsets.only(left: 24, right: 24, bottom: 8, top: 8)) + : const SizedBox.shrink(), + ), + ]) + ), ); } 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 24db15efb..a994786a3 100644 --- a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart +++ b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart @@ -73,7 +73,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/quotas/presentation/quotas_controller_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'; @@ -103,7 +103,7 @@ class MailboxDashBoardBindings extends BaseBindings { ThreadBindings().dependencies(); EmailBindings().dependencies(); SearchEmailBindings().dependencies(); - QuotasBindings().dependencies(); + QuotasControllerBindings().dependencies(); } @override diff --git a/lib/features/quotas/data/network/quotas_api.dart b/lib/features/quotas/data/network/quotas_api.dart index 7511ff8ca..c5d30da39 100644 --- a/lib/features/quotas/data/network/quotas_api.dart +++ b/lib/features/quotas/data/network/quotas_api.dart @@ -36,6 +36,5 @@ class QuotasAPI { } else { throw NotFoundQuotasException(); } - } } diff --git a/lib/features/quotas/presentation/model/quotas_state.dart b/lib/features/quotas/presentation/model/quotas_state.dart index e955bf20a..237ba8dd4 100644 --- a/lib/features/quotas/presentation/model/quotas_state.dart +++ b/lib/features/quotas/presentation/model/quotas_state.dart @@ -1,16 +1,16 @@ -import 'dart:ui'; - import 'package:core/core.dart'; import 'package:flutter/widgets.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; enum QuotasState { + notAvailable, normal, runningOutOfStorage, runOutOfStorage; Color getColorProgress() { switch(this) { + case QuotasState.notAvailable: case QuotasState.normal: return AppColor.primaryColor; case QuotasState.runningOutOfStorage: @@ -22,6 +22,7 @@ enum QuotasState { Color getColorQuotasFooterText() { switch(this) { + case QuotasState.notAvailable: case QuotasState.normal: case QuotasState.runningOutOfStorage: return AppColor.loginTextFieldHintColor; @@ -32,6 +33,7 @@ enum QuotasState { String getQuotasFooterText(BuildContext context, num usedCapacity, num softLimitCapacity) { switch(this) { + case QuotasState.notAvailable: case QuotasState.normal: case QuotasState.runningOutOfStorage: return AppLocalizations.of(context).textQuotasUsed( @@ -45,6 +47,7 @@ enum QuotasState { String getIconWarningBanner(ImagePaths imagePaths) { switch(this) { + case QuotasState.notAvailable: case QuotasState.normal: case QuotasState.runningOutOfStorage: return imagePaths.icQuotasWarning; @@ -55,6 +58,7 @@ enum QuotasState { Color getBackgroundColorWarningBanner() { switch(this) { + case QuotasState.notAvailable: case QuotasState.normal: case QuotasState.runningOutOfStorage: return AppColor.colorBackgroundQuotasWarning.withOpacity(0.12); @@ -65,6 +69,7 @@ enum QuotasState { String getTitleWarningBanner(BuildContext context, num progress) { switch(this) { + case QuotasState.notAvailable: case QuotasState.normal: case QuotasState.runningOutOfStorage: return AppLocalizations.of(context).textQuotasRunningOutOfStorageTitle(progress.toDouble() * 100); @@ -75,6 +80,7 @@ enum QuotasState { String getContentWarningBanner(BuildContext context) { switch(this) { + case QuotasState.notAvailable: case QuotasState.normal: case QuotasState.runningOutOfStorage: return AppLocalizations.of(context).textQuotasRunningOutOfStorageContent; diff --git a/lib/features/quotas/presentation/quotas_controller.dart b/lib/features/quotas/presentation/quotas_controller.dart index bb53f1f02..71d87ab56 100644 --- a/lib/features/quotas/presentation/quotas_controller.dart +++ b/lib/features/quotas/presentation/quotas_controller.dart @@ -1,4 +1,5 @@ import 'package:core/core.dart'; +import 'package:core/utils/double_convert.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart'; @@ -17,8 +18,7 @@ class QuotasController extends BaseController { final usedCapacity = Rx(0); final limitCapacity = Rx(0); final warningLimitCapacity = Rx(0); - final enableShowQuotas = false.obs; - final quotasState = QuotasState.normal.obs; + final quotasState = QuotasState.notAvailable.obs; final warningProgressConstant = 0.9; late Worker accountIdWorker; @@ -27,7 +27,7 @@ class QuotasController extends BaseController { : 0; bool get enableShowWarningQuotas => - enableShowQuotas.isTrue && + quotasState.value != QuotasState.notAvailable && (quotasState.value == QuotasState.runningOutOfStorage || quotasState.value == QuotasState.runOutOfStorage); @@ -36,14 +36,6 @@ class QuotasController extends BaseController { QuotasController(this._getQuotasInteractor); - void _initWorker() { - accountIdWorker = ever(mailboxDashBoardController.accountId, (accountId) { - if (accountId is AccountId && mailboxDashBoardController.sessionCurrent!= null) { - _getQuotasAction(accountId, mailboxDashBoardController.sessionCurrent!); - } - }); - } - void _getQuotasAction(AccountId accountId, Session session) { try { requireCapability(session, accountId, [CapabilityIdentifier.jmapQuota]); @@ -72,9 +64,9 @@ class QuotasController extends BaseController { void _handleGetQuotasSuccess(GetQuotasSuccess success) { try { final quotas = success.quotas.firstWhere((e) => e.resourceType == ResourceType.octets); - usedCapacity.value = quotas.used.value; - warningLimitCapacity.value = quotas.limit.value * warningProgressConstant; - limitCapacity.value = quotas.limit.value; + usedCapacity.value = DoubleConvert.bytesToGigaBytes(quotas.used.value); + warningLimitCapacity.value = DoubleConvert.bytesToGigaBytes(quotas.limit.value * warningProgressConstant); + limitCapacity.value = DoubleConvert.bytesToGigaBytes(quotas.limit.value); if(usedCapacity.value >= limitCapacity.value) { quotasState.value = QuotasState.runOutOfStorage; } else if (usedCapacity.value >= warningLimitCapacity.value) { @@ -82,13 +74,24 @@ class QuotasController extends BaseController { } else { quotasState.value = QuotasState.normal; } - enableShowQuotas.value = true; } catch (e) { - enableShowQuotas.value = false; + quotasState.value = QuotasState.notAvailable; logError('QuotasController::_handleGetQuotasSuccess():[NotFoundException]: $e'); } } + void covertBytesToGB() { + + } + + void _initWorker() { + accountIdWorker = ever(mailboxDashBoardController.accountId, (accountId) { + if (accountId is AccountId && mailboxDashBoardController.sessionCurrent!= null) { + _getQuotasAction(accountId, mailboxDashBoardController.sessionCurrent!); + } + }); + } + @override void onInit() { _initWorker(); diff --git a/lib/features/quotas/presentation/quotas_bindings.dart b/lib/features/quotas/presentation/quotas_controller_bindings.dart similarity index 91% rename from lib/features/quotas/presentation/quotas_bindings.dart rename to lib/features/quotas/presentation/quotas_controller_bindings.dart index e70029a54..1c3fd540b 100644 --- a/lib/features/quotas/presentation/quotas_bindings.dart +++ b/lib/features/quotas/presentation/quotas_controller_bindings.dart @@ -9,7 +9,7 @@ import 'package:tmail_ui_user/features/quotas/domain/use_case/get_quotas_interac 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 { +class QuotasControllerBindings extends BaseBindings { @override void bindingsController() { Get.put(QuotasController(Get.find())); @@ -17,7 +17,7 @@ class QuotasBindings extends BaseBindings { @override void bindingsDataSource() { - Get.lazyPut(() => Get.find()); + Get.lazyPut(() => (Get.find())); } @override diff --git a/lib/features/quotas/presentation/widget/quotas_footer_widget.dart b/lib/features/quotas/presentation/widget/quotas_footer_widget.dart index 425db8c45..f62b2d854 100644 --- a/lib/features/quotas/presentation/widget/quotas_footer_widget.dart +++ b/lib/features/quotas/presentation/widget/quotas_footer_widget.dart @@ -2,6 +2,7 @@ import 'package:core/core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/quotas/presentation/model/quotas_state.dart'; import 'package:tmail_ui_user/features/quotas/presentation/quotas_controller.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -11,7 +12,7 @@ class QuotasFooterWidget extends GetWidget { @override Widget build(BuildContext context) { return Obx( - () => controller.enableShowQuotas.value + () => controller.quotasState.value != QuotasState.notAvailable ? Container( color: AppColor.colorBgDesktop, padding: padding ?? const EdgeInsets.all(24), diff --git a/pubspec.lock b/pubspec.lock index 476303d8e..e27bf3800 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,7 +21,7 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.3.2" + version: "3.3.4" args: dependency: transitive description: @@ -757,7 +757,7 @@ packages: description: path: "." ref: master - resolved-ref: ea636193b15a49e9d59dab143e957f529e1bd836 + resolved-ref: "66ef334ac2cf4d5cb30835b30094a51802fae2ba" url: "https://github.com/linagora/jmap-dart-client.git" source: git version: "0.0.1" @@ -1075,7 +1075,7 @@ packages: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.3" pubspec_parse: dependency: transitive description: