diff --git a/assets/images/ic_mailbox_action_required.svg b/assets/images/ic_mailbox_action_required.svg
new file mode 100644
index 000000000..0b67f0ee0
--- /dev/null
+++ b/assets/images/ic_mailbox_action_required.svg
@@ -0,0 +1,5 @@
+
diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart
index 7527c5610..4608b9ace 100644
--- a/core/lib/presentation/resources/image_paths.dart
+++ b/core/lib/presentation/resources/image_paths.dart
@@ -45,6 +45,7 @@ class ImagePaths {
String get icMailboxSpam => _getImagePath('ic_mailbox_spam.svg');
String get icMailboxTrash => _getImagePath('ic_mailbox_trash.svg');
String get icMailboxFavorite => _getImagePath('ic_mailbox_favorite.svg');
+ String get icMailboxActionRequired => _getImagePath('ic_mailbox_action_required.svg');
String get icFilterSelected => _getImagePath('ic_filter_selected.svg');
String get icFilterMessageAll => _getImagePath('ic_filter_message_all.svg');
String get icFilterMessageAttachments => _getImagePath('ic_filter_message_attachments.svg');
diff --git a/lib/features/mailbox/presentation/extensions/handle_action_required_tab_extension.dart b/lib/features/mailbox/presentation/extensions/handle_action_required_tab_extension.dart
new file mode 100644
index 000000000..40d08bacc
--- /dev/null
+++ b/lib/features/mailbox/presentation/extensions/handle_action_required_tab_extension.dart
@@ -0,0 +1,91 @@
+import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
+import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
+import 'package:model/mailbox/presentation_mailbox.dart';
+import 'package:tmail_ui_user/features/base/base_mailbox_controller.dart';
+import 'package:tmail_ui_user/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart';
+import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
+import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
+import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree.dart';
+import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
+import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_ai_action_extension.dart';
+import 'package:tmail_ui_user/main/routes/route_navigation.dart';
+
+extension HandleActionRequiredTabExtension on BaseMailboxController {
+ void setUpActionRequiredFolder(
+ MailboxDashBoardController dashboardController,
+ ) {
+ if (!dashboardController.isAiCapabilitySupported) return;
+
+ dashboardController.actionRequiredFolderController.getCountEmails(
+ session: dashboardController.sessionCurrent,
+ accountId: dashboardController.accountId.value,
+ );
+ }
+
+ void onActionRequiredFolderCountChanged(int count) {
+ if (count > 0) {
+ _addActionRequiredFolder(count);
+ } else {
+ _removeActionRequiredFolder();
+ }
+ }
+
+ void _addActionRequiredFolder(int count) {
+ final folder = _buildActionRequiredFolder(count);
+
+ _addToDefaultMailboxTree(folder);
+ _addToAllMailboxes(folder);
+ }
+
+ PresentationMailbox _buildActionRequiredFolder(int count) {
+ final base = PresentationMailbox.actionRequiredFolder;
+
+ return base.copyWith(
+ displayName:
+ currentContext != null ? base.getDisplayName(currentContext!) : null,
+ totalEmails: TotalEmails(UnsignedInt(count)),
+ unreadEmails: UnreadEmails(UnsignedInt(count)),
+ );
+ }
+
+ void _addToDefaultMailboxTree(PresentationMailbox folder) {
+ final root = defaultMailboxTree.value.root;
+ final children = List.from(root.childrenItems ?? []);
+
+ children.insertAfterStarredOrInbox(MailboxNode(folder));
+
+ defaultMailboxTree.value = MailboxTree(
+ root.copyWith(children: children),
+ );
+ }
+
+ void _addToAllMailboxes(PresentationMailbox folder) {
+ if (_allMailboxesContains(folder.id)) return;
+ allMailboxes.add(folder);
+ }
+
+ void _removeActionRequiredFolder() {
+ final folder = PresentationMailbox.actionRequiredFolder;
+
+ _removeFromDefaultMailboxTree(folder.id);
+ _removeFromAllMailboxes(folder.id);
+ }
+
+ void _removeFromDefaultMailboxTree(MailboxId folderId) {
+ final root = defaultMailboxTree.value.root;
+ final children = List.from(root.childrenItems ?? [])
+ ..removeWhere((node) => node.item.id == folderId);
+
+ defaultMailboxTree.value = MailboxTree(
+ root.copyWith(children: children),
+ );
+ }
+
+ void _removeFromAllMailboxes(MailboxId folderId) {
+ allMailboxes.removeWhere((mailbox) => mailbox.id == folderId);
+ }
+
+ bool _allMailboxesContains(MailboxId id) {
+ return allMailboxes.any((mailbox) => mailbox.id == id);
+ }
+}
diff --git a/lib/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart b/lib/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart
index 8e34e9096..98d2a3ff8 100644
--- a/lib/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart
+++ b/lib/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart
@@ -5,20 +5,60 @@ import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.d
extension ListMailboxNodeExtension on List {
List get mailboxIds => map((node) => node.item.id).toList();
+ /// Insert [newNode] after Inbox if present, otherwise at the beginning.
void insertAfterInbox(MailboxNode newNode) {
- final alreadyExists = any((node) => node.item.id == newNode.item.id);
- if (alreadyExists) return;
-
- final index = indexWhere(
- (node) =>
- node.item.role?.value == PresentationMailbox.inboxRole ||
- node.item.name?.name.toLowerCase() == 'inbox',
+ insertAfterByPriority(
+ newNode,
+ [_isInbox],
);
+ }
- if (index != -1) {
- insert(index + 1, newNode);
- } else {
- insert(0, newNode);
+ /// Insert [newNode] after Starred if present,
+ /// otherwise after Inbox, otherwise at the beginning.
+ void insertAfterStarredOrInbox(MailboxNode newNode) {
+ insertAfterByPriority(
+ newNode,
+ [
+ _isStarred,
+ _isInbox,
+ ],
+ );
+ }
+
+ /// Insert [newNode] after the first mailbox matching [priorities].
+ /// If none match, inserts at the beginning.
+ void insertAfterByPriority(
+ MailboxNode newNode,
+ List priorities,
+ ) {
+ if (_containsMailbox(newNode)) return;
+
+ for (final predicate in priorities) {
+ final index = indexWhere(predicate);
+ if (index != -1) {
+ insert(index + 1, newNode);
+ return;
+ }
}
+
+ insert(0, newNode);
+ }
+
+ bool _isInbox(MailboxNode node) {
+ return node.item.role?.value == PresentationMailbox.inboxRole ||
+ _equalsIgnoreCase(node.item.name?.name, 'inbox');
+ }
+
+ bool _isStarred(MailboxNode node) {
+ return node.item.role?.value == PresentationMailbox.favoriteRole ||
+ _equalsIgnoreCase(node.item.name?.name, 'starred');
+ }
+
+ bool _containsMailbox(MailboxNode node) {
+ return any((e) => e.item.id == node.item.id);
+ }
+
+ bool _equalsIgnoreCase(String? value, String expected) {
+ return value != null && value.toLowerCase() == expected;
}
}
diff --git a/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart b/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart
index c91f17709..5798c6716 100644
--- a/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart
+++ b/lib/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart
@@ -17,6 +17,8 @@ extension PresentationMailboxExtension on PresentationMailbox {
return AppLocalizations.of(context).inboxMailboxDisplayName;
case PresentationMailbox.favoriteRole:
return AppLocalizations.of(context).favoriteMailboxDisplayName;
+ case PresentationMailbox.actionRequiredRole:
+ return AppLocalizations.of(context).actionRequiredMailboxDisplayName;
case PresentationMailbox.archiveRole:
return AppLocalizations.of(context).archiveMailboxDisplayName;
case PresentationMailbox.draftsRole:
@@ -44,6 +46,10 @@ extension PresentationMailboxExtension on PresentationMailbox {
switch(role!.value.toLowerCase()) {
case PresentationMailbox.inboxRole:
return appLocalizations.inboxMailboxDisplayName;
+ case PresentationMailbox.favoriteRole:
+ return appLocalizations.favoriteMailboxDisplayName;
+ case PresentationMailbox.actionRequiredRole:
+ return appLocalizations.actionRequiredMailboxDisplayName;
case PresentationMailbox.archiveRole:
return appLocalizations.archiveMailboxDisplayName;
case PresentationMailbox.draftsRole:
@@ -73,6 +79,8 @@ extension PresentationMailboxExtension on PresentationMailbox {
return imagePaths.icMailboxInbox;
case PresentationMailbox.favoriteRole:
return imagePaths.icMailboxFavorite;
+ case PresentationMailbox.actionRequiredRole:
+ return imagePaths.icMailboxActionRequired;
case PresentationMailbox.draftsRole:
return imagePaths.icMailboxDrafts;
case PresentationMailbox.outboxRole:
diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart
index b60fc7167..5af64b502 100644
--- a/lib/features/mailbox/presentation/mailbox_controller.dart
+++ b/lib/features/mailbox/presentation/mailbox_controller.dart
@@ -69,6 +69,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/usecases/subaddressing_int
import 'package:tmail_ui_user/features/mailbox/domain/usecases/subscribe_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/subscribe_multiple_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart';
+import 'package:tmail_ui_user/features/mailbox/presentation/extensions/handle_action_required_tab_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/handle_favorite_tab_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/mixin/mailbox_widget_mixin.dart';
@@ -264,6 +265,7 @@ class MailboxController extends BaseMailboxController
(failure) {
if (failure is GetAllMailboxFailure) {
addFavoriteFolderToMailboxList();
+ setUpActionRequiredFolder(mailboxDashBoardController);
mailboxDashBoardController.updateRefreshAllMailboxState(Left(RefreshAllMailboxFailure()));
showRetryToast(failure);
}
@@ -271,6 +273,7 @@ class MailboxController extends BaseMailboxController
(success) {
if (success is GetAllMailboxSuccess) {
addFavoriteFolderToMailboxList();
+ setUpActionRequiredFolder(mailboxDashBoardController);
mailboxDashBoardController.updateRefreshAllMailboxState(Right(RefreshAllMailboxSuccess()));
_handleCreateDefaultFolderIfMissing(mailboxDashBoardController.mapDefaultMailboxIdByRole);
_handleDataFromNavigationRouter();
@@ -280,6 +283,7 @@ class MailboxController extends BaseMailboxController
}
} else if (success is CreateDefaultMailboxAllSuccess) {
addFavoriteFolderToMailboxList();
+ setUpActionRequiredFolder(mailboxDashBoardController);
}
});
}
@@ -434,6 +438,11 @@ class MailboxController extends BaseMailboxController
);
}
});
+
+ ever(
+ mailboxDashBoardController.actionRequiredFolderController.actionRequiredFolderCount,
+ onActionRequiredFolderCountChanged,
+ );
}
void _handleMarkEmailsAsReadOrUnread({
diff --git a/lib/features/mailbox_dashboard/presentation/bindings/action_required_interactor_bindings.dart b/lib/features/mailbox_dashboard/presentation/bindings/action_required_interactor_bindings.dart
new file mode 100644
index 000000000..bf5aa08e0
--- /dev/null
+++ b/lib/features/mailbox_dashboard/presentation/bindings/action_required_interactor_bindings.dart
@@ -0,0 +1,79 @@
+import 'package:core/data/model/source_type/data_source_type.dart';
+import 'package:get/get.dart';
+import 'package:tmail_ui_user/features/base/interactors_bindings.dart';
+import 'package:tmail_ui_user/features/caching/caching_manager.dart';
+import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
+import 'package:tmail_ui_user/features/mailbox/data/datasource_impl/state_datasource_impl.dart';
+import 'package:tmail_ui_user/features/mailbox/data/local/state_cache_manager.dart';
+import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
+import 'package:tmail_ui_user/features/thread/data/datasource_impl/local_thread_datasource_impl.dart';
+import 'package:tmail_ui_user/features/thread/data/datasource_impl/thread_datasource_impl.dart';
+import 'package:tmail_ui_user/features/thread/data/local/email_cache_manager.dart';
+import 'package:tmail_ui_user/features/thread/data/network/thread_api.dart';
+import 'package:tmail_ui_user/features/thread/data/network/thread_isolate_worker.dart';
+import 'package:tmail_ui_user/features/thread/data/repository/thread_repository_impl.dart';
+import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart';
+import 'package:tmail_ui_user/features/thread/domain/usecases/get_count_unread_emails_in_folder_interactor.dart';
+import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
+import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
+import 'package:tmail_ui_user/main/utils/ios_sharing_manager.dart';
+
+class ActionRequiredInteractorBindings extends InteractorsBindings {
+ @override
+ void bindingsDataSource() {
+ Get.lazyPut(() => Get.find());
+ Get.lazyPut(() => Get.find());
+ }
+
+ @override
+ void bindingsDataSourceImpl() {
+ Get.lazyPut(
+ () => ThreadDataSourceImpl(
+ Get.find(),
+ Get.find(),
+ Get.find(),
+ ),
+ );
+ Get.lazyPut(
+ () => LocalThreadDataSourceImpl(
+ Get.find(),
+ Get.find(),
+ Get.find(),
+ ),
+ );
+ Get.lazyPut(
+ () => StateDataSourceImpl(
+ Get.find(),
+ Get.find(),
+ Get.find(),
+ ),
+ );
+ }
+
+ @override
+ void bindingsInteractor() {
+ Get.lazyPut(
+ () => GetCountUnreadEmailsInFolderInteractor(
+ Get.find(),
+ ),
+ );
+ }
+
+ @override
+ void bindingsRepository() {
+ Get.lazyPut(() => Get.find());
+ }
+
+ @override
+ void bindingsRepositoryImpl() {
+ Get.lazyPut(
+ () => ThreadRepositoryImpl(
+ {
+ DataSourceType.network: Get.find(),
+ DataSourceType.local: Get.find()
+ },
+ Get.find(),
+ ),
+ );
+ }
+}
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 c4886dd99..c8b1fab2a 100644
--- a/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart
+++ b/lib/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart
@@ -106,6 +106,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_e
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_last_time_dismissed_spam_reported_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_spam_report_state_interactor.dart';
import 'package:tmail_ui_user/features/download/presentation/bindings/download_interactor_bindings.dart';
+import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/action_required_folder_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
import 'package:tmail_ui_user/features/download/presentation/controllers/download_controller.dart';
@@ -209,6 +210,8 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.lazyPut(() => ComposerManager());
+ Get.put(ActionRequiredFolderController());
+
Get.put(MailboxDashBoardController(
Get.find(),
Get.find(),
diff --git a/lib/features/mailbox_dashboard/presentation/controller/action_required_folder_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/action_required_folder_controller.dart
new file mode 100644
index 000000000..e48d7341f
--- /dev/null
+++ b/lib/features/mailbox_dashboard/presentation/controller/action_required_folder_controller.dart
@@ -0,0 +1,82 @@
+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/core/session/session.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/mailbox_dashboard/presentation/bindings/action_required_interactor_bindings.dart';
+import 'package:tmail_ui_user/features/thread/domain/exceptions/thread_exceptions.dart';
+import 'package:tmail_ui_user/features/thread/domain/state/get_count_emails_in_folder_state.dart';
+import 'package:tmail_ui_user/features/thread/domain/usecases/get_count_unread_emails_in_folder_interactor.dart';
+import 'package:tmail_ui_user/main/routes/route_navigation.dart';
+
+class ActionRequiredFolderController extends BaseController {
+ final actionRequiredFolderCount = RxInt(0);
+
+ GetCountUnreadEmailsInFolderInteractor?
+ _getCountUnreadEmailsInFolderInteractor;
+
+ void injectBinding() {
+ ActionRequiredInteractorBindings().dependencies();
+
+ _getCountUnreadEmailsInFolderInteractor =
+ getBinding();
+ }
+
+ Future getCountEmails({
+ required Session? session,
+ required AccountId? accountId,
+ }) async {
+ if (_getCountUnreadEmailsInFolderInteractor == null) {
+ consumeState(Stream.value(
+ Left(GetCountUnreadEmailsInFolderFailure(InteractorIsNullException())),
+ ));
+ return;
+ }
+
+ if (session == null) {
+ consumeState(Stream.value(
+ Left(GetCountUnreadEmailsInFolderFailure(NotFoundSessionException())),
+ ));
+ return;
+ }
+
+ if (accountId == null) {
+ consumeState(Stream.value(
+ Left(GetCountUnreadEmailsInFolderFailure(NotFoundAccountIdException())),
+ ));
+ return;
+ }
+
+ consumeState(_getCountUnreadEmailsInFolderInteractor!.execute(
+ session: session,
+ accountId: accountId,
+ ));
+ }
+
+ @override
+ void handleSuccessViewState(Success success) {
+ if (success is GetCountUnreadEmailsInFolderSuccess) {
+ actionRequiredFolderCount.value = success.count;
+ } else {
+ super.handleSuccessViewState(success);
+ }
+ }
+
+ @override
+ void handleFailureViewState(Failure failure) {
+ if (failure is GetCountUnreadEmailsInFolderFailure) {
+ actionRequiredFolderCount.value = 0;
+ } else {
+ super.handleFailureViewState(failure);
+ }
+ }
+
+ @override
+ void onClose() {
+ _getCountUnreadEmailsInFolderInteractor = null;
+ super.onClose();
+ }
+}
diff --git a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart
index cb81c1890..79b7f41b0 100644
--- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart
+++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart
@@ -117,6 +117,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_te
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/store_email_sort_order_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/download_ui_action.dart';
+import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/action_required_folder_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/app_grid_dashboard_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/search_controller.dart' as search;
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/spam_report_controller.dart';
@@ -124,6 +125,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/cleanup_recent_search_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/delete_emails_in_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_action_type_for_email_selection.dart';
+import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_ai_action_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_clear_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_create_new_rule_filter.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_preferences_setting_extension.dart';
@@ -237,6 +239,8 @@ class MailboxDashBoardController extends ReloadableController
final getStoredOidcConfigurationInteractor =
Get.find();
final getTokenOIDCInteractor = Get.find();
+ final actionRequiredFolderController =
+ Get.find();
final MoveToMailboxInteractor _moveToMailboxInteractor;
final DeleteEmailPermanentlyInteractor _deleteEmailPermanentlyInteractor;
@@ -874,6 +878,9 @@ class MailboxDashBoardController extends ReloadableController
if (PlatformInfo.isMobile) {
injectFCMBindings(session, currentAccountId);
}
+ if (isAiCapabilitySupported) {
+ actionRequiredFolderController.injectBinding();
+ }
_getVacationResponse();
spamReportController.getSpamReportStateAction();
diff --git a/lib/features/search/mailbox/presentation/search_mailbox_controller.dart b/lib/features/search/mailbox/presentation/search_mailbox_controller.dart
index d6f0a8280..474642d06 100644
--- a/lib/features/search/mailbox/presentation/search_mailbox_controller.dart
+++ b/lib/features/search/mailbox/presentation/search_mailbox_controller.dart
@@ -58,6 +58,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/usecases/subaddressing_int
import 'package:tmail_ui_user/features/mailbox/domain/usecases/subscribe_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/subscribe_multiple_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/action/mailbox_ui_action.dart';
+import 'package:tmail_ui_user/features/mailbox/presentation/extensions/handle_action_required_tab_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/handle_favorite_tab_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/extensions/presentation_mailbox_extension.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
@@ -253,6 +254,12 @@ class SearchMailboxController extends BaseMailboxController with MailboxActionHa
);
}
});
+
+ ever(
+ dashboardController
+ .actionRequiredFolderController.actionRequiredFolderCount,
+ onActionRequiredFolderCountChanged,
+ );
}
void _registerInputFocusListener() {
diff --git a/lib/features/thread/data/repository/thread_repository_impl.dart b/lib/features/thread/data/repository/thread_repository_impl.dart
index f85eec412..3052a5d47 100644
--- a/lib/features/thread/data/repository/thread_repository_impl.dart
+++ b/lib/features/thread/data/repository/thread_repository_impl.dart
@@ -16,6 +16,7 @@ import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart';
+import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
@@ -523,4 +524,22 @@ class ThreadRepositoryImpl extends ThreadRepository {
);
yield emailResponse;
}
+
+ @override
+ Future getCountUnreadEmailsInFolder({
+ required Session session,
+ required AccountId accountId,
+ }) async {
+ final networkDataSource = mapDataSource[DataSourceType.network]!;
+ final emailResponse = await networkDataSource.getAllEmail(
+ session,
+ accountId,
+ filter: EmailFilterCondition(
+ hasKeyword: KeyWordIdentifierExtension.needActionMail.value,
+ notKeyword: KeyWordIdentifier.emailSeen.value,
+ ),
+ properties: Properties({EmailProperty.id}),
+ );
+ return emailResponse.emailList?.length ?? 0;
+ }
}
\ No newline at end of file
diff --git a/lib/features/thread/domain/exceptions/thread_exceptions.dart b/lib/features/thread/domain/exceptions/thread_exceptions.dart
index 134c9ce63..8941b507a 100644
--- a/lib/features/thread/domain/exceptions/thread_exceptions.dart
+++ b/lib/features/thread/domain/exceptions/thread_exceptions.dart
@@ -1,2 +1,3 @@
+class NotFoundEmailsDeletedException implements Exception {}
-class NotFoundEmailsDeletedException implements Exception {}
\ No newline at end of file
+class InteractorIsNullException implements Exception {}
\ No newline at end of file
diff --git a/lib/features/thread/domain/repository/thread_repository.dart b/lib/features/thread/domain/repository/thread_repository.dart
index 686b46c0a..35005de71 100644
--- a/lib/features/thread/domain/repository/thread_repository.dart
+++ b/lib/features/thread/domain/repository/thread_repository.dart
@@ -93,4 +93,9 @@ abstract class ThreadRepository {
);
Future clearEmailCacheAndStateCache(AccountId accountId, Session session);
+
+ Future getCountUnreadEmailsInFolder({
+ required Session session,
+ required AccountId accountId,
+ });
}
\ No newline at end of file
diff --git a/lib/features/thread/domain/state/get_count_emails_in_folder_state.dart b/lib/features/thread/domain/state/get_count_emails_in_folder_state.dart
new file mode 100644
index 000000000..a5b9420b4
--- /dev/null
+++ b/lib/features/thread/domain/state/get_count_emails_in_folder_state.dart
@@ -0,0 +1,18 @@
+import 'package:core/presentation/state/failure.dart';
+import 'package:core/presentation/state/success.dart';
+
+class GettingCountUnreadEmailsInFolder extends LoadingState {}
+
+class GetCountUnreadEmailsInFolderSuccess extends UIState {
+ final int count;
+
+ GetCountUnreadEmailsInFolderSuccess({required this.count});
+
+ @override
+ List