TF-1715 Add favorite folder to mailbox left menu

This commit is contained in:
dab246
2025-10-30 10:20:33 +07:00
committed by Dat H. Pham
parent fbb79e17a3
commit d85e691d98
11 changed files with 211 additions and 3 deletions
@@ -0,0 +1,48 @@
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/main/routes/route_navigation.dart';
extension HandleFavoriteTabExtension on BaseMailboxController {
void addFavoriteFolderToMailboxList() {
PresentationMailbox favoriteFolder = PresentationMailbox.favoriteFolder;
if (currentContext != null) {
favoriteFolder = favoriteFolder.copyWith(
displayName: favoriteFolder.getDisplayName(currentContext!),
);
}
_addFavoriteFolderToDefaultMailboxTree(favoriteFolder);
_addFavoriteFolderToAllMailboxes(favoriteFolder);
}
void _addFavoriteFolderToDefaultMailboxTree(
PresentationMailbox favoriteFolder,
) {
final defaultMailboxNode = defaultMailboxTree.value.root;
List<MailboxNode> currentDefaultFolders =
defaultMailboxNode.childrenItems ?? [];
if (currentDefaultFolders.isEmpty) {
currentDefaultFolders.add(MailboxNode(favoriteFolder));
} else {
currentDefaultFolders.insertAfterInbox(MailboxNode(favoriteFolder));
}
defaultMailboxTree.value = MailboxTree(
defaultMailboxNode.copyWith(children: currentDefaultFolders),
);
}
void _addFavoriteFolderToAllMailboxes(PresentationMailbox favoriteFolder) {
final alreadyExists = allMailboxes.any(
(mailbox) => mailbox.id == favoriteFolder.id,
);
if (alreadyExists) return;
allMailboxes.add(favoriteFolder);
}
}
@@ -1,7 +1,24 @@
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart';
extension ListMailboxNodeExtension on List<MailboxNode> {
List<MailboxId> get mailboxIds => map((node) => node.item.id).toList();
}
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',
);
if (index != -1) {
insert(index + 1, newNode);
} else {
insert(0, newNode);
}
}
}
@@ -15,6 +15,8 @@ extension PresentationMailboxExtension on PresentationMailbox {
switch(role!.value.toLowerCase()) {
case PresentationMailbox.inboxRole:
return AppLocalizations.of(context).inboxMailboxDisplayName;
case PresentationMailbox.favoriteRole:
return AppLocalizations.of(context).favoriteMailboxDisplayName;
case PresentationMailbox.archiveRole:
return AppLocalizations.of(context).archiveMailboxDisplayName;
case PresentationMailbox.draftsRole:
@@ -69,6 +71,8 @@ extension PresentationMailboxExtension on PresentationMailbox {
switch(role!.value) {
case PresentationMailbox.inboxRole:
return imagePaths.icMailboxInbox;
case PresentationMailbox.favoriteRole:
return imagePaths.icMailboxFavorite;
case PresentationMailbox.draftsRole:
return imagePaths.icMailboxDrafts;
case PresentationMailbox.outboxRole:
@@ -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_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';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart';
@@ -256,12 +257,14 @@ class MailboxController extends BaseMailboxController
viewState.value.fold(
(failure) {
if (failure is GetAllMailboxFailure) {
addFavoriteFolderToMailboxList();
mailboxDashBoardController.updateRefreshAllMailboxState(Left(RefreshAllMailboxFailure()));
showRetryToast(failure);
}
},
(success) {
if (success is GetAllMailboxSuccess) {
addFavoriteFolderToMailboxList();
mailboxDashBoardController.updateRefreshAllMailboxState(Right(RefreshAllMailboxSuccess()));
_handleCreateDefaultFolderIfMissing(mailboxDashBoardController.mapDefaultMailboxIdByRole);
_handleDataFromNavigationRouter();
@@ -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_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';
import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart';
@@ -207,6 +208,20 @@ class SearchMailboxController extends BaseMailboxController with MailboxActionHa
}
}
@override
void onDone() {
super.onDone();
viewState.value.fold((failure) {
if (failure is GetAllMailboxFailure) {
addFavoriteFolderToMailboxList();
}
}, (success) {
if (success is GetAllMailboxSuccess) {
addFavoriteFolderToMailboxList();
}
});
}
void _initializeDebounceTimeTextSearchChange() {
_deBouncerTime = Debouncer<String>(
const Duration(milliseconds: 300),
@@ -450,7 +465,6 @@ class SearchMailboxController extends BaseMailboxController with MailboxActionHa
}
}
void _handleSubAddressingAction(
MailboxId mailboxId,
Map<String, List<String>?>? currentRights,