From 636df94458ef22f6cbaeea7e0c2541778e347fa3 Mon Sep 17 00:00:00 2001 From: Dat Dang Date: Tue, 18 Feb 2025 14:06:08 +0700 Subject: [PATCH] TF-2469 Fix email set into root mailbox's SENT instead of team mailbox's SENT (#3482) --- docs/adr/0057-team-mailboxes-matching.md | 26 +++++++++++++++++++ .../presentation/composer_controller.dart | 21 ++++++++------- ...aft_mailbox_id_for_composer_extension.dart | 22 ++++++++++++++++ ...box_mailbox_id_for_composer_extension.dart | 22 ++++++++++++++++ ...ent_mailbox_id_for_composer_extension.dart | 21 +++++++++++++++ .../composer_controller_test.dart | 3 +++ 6 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 docs/adr/0057-team-mailboxes-matching.md create mode 100644 lib/features/composer/presentation/extensions/get_draft_mailbox_id_for_composer_extension.dart create mode 100644 lib/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart create mode 100644 lib/features/composer/presentation/extensions/get_sent_mailbox_id_for_composer_extension.dart diff --git a/docs/adr/0057-team-mailboxes-matching.md b/docs/adr/0057-team-mailboxes-matching.md new file mode 100644 index 000000000..26e50e5fd --- /dev/null +++ b/docs/adr/0057-team-mailboxes-matching.md @@ -0,0 +1,26 @@ +# 57. Team Mailboxes Matching + +Date: 2025-02-18 + +## Status + +Accepted + +## Context + +- Team mailboxes were not considered when sending emails +- Sent emails were saved to default sent mailbox, although selected identity's email was based on team mailbox email +- User does not have permission to edit mailboxes of team mailboxes + +## Decision + +- Instead of hard coding default sent mailbox, sent emails will be saved to mailbox based on + - identity's email + - mailbox's name (hard coded English) +- Only when there's no matching mailbox, default sent mailbox will be used +- Same logic is applied to drafts mailbox and outbox mailbox + +## Consequences + +- Team mailboxes will be considered when sending emails +- Potentially, if team mailboxes existed but the name is not in English, sent emails will be saved to default sent mailbox diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index 8ce97eab0..5671e3be6 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -56,6 +56,9 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/save_composer_ca import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/get_draft_mailbox_id_for_composer_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart'; +import 'package:tmail_ui_user/features/composer/presentation/extensions/get_sent_mailbox_id_for_composer_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/list_identities_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/list_shared_media_file_extension.dart'; import 'package:tmail_ui_user/features/composer/presentation/mixin/drag_drog_file_mixin.dart'; @@ -481,9 +484,9 @@ class ComposerController extends BaseController identity: identitySelected.value, attachments: uploadController.attachmentsUploaded, inlineAttachments: uploadController.mapInlineAttachments, - outboxMailboxId: mailboxDashBoardController.outboxMailbox?.mailboxId, - sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent], - draftsMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleDrafts], + outboxMailboxId: getOutboxMailboxIdForComposer(), + sentMailboxId: getSentMailboxIdForComposer(), + draftsMailboxId: getDraftMailboxIdForComposer(), draftsEmailId: getDraftEmailId(), answerForwardEmailId: composerArguments.value!.presentationEmail?.id, unsubscribeEmailId: composerArguments.value!.previousEmailId, @@ -1059,8 +1062,8 @@ class ComposerController extends BaseController identity: identitySelected.value, attachments: uploadController.attachmentsUploaded, inlineAttachments: uploadController.mapInlineAttachments, - outboxMailboxId: mailboxDashBoardController.outboxMailbox?.mailboxId, - sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent], + outboxMailboxId: getOutboxMailboxIdForComposer(), + sentMailboxId: getSentMailboxIdForComposer(), draftsEmailId: getDraftEmailId(), answerForwardEmailId: composerArguments.value!.presentationEmail?.id, unsubscribeEmailId: composerArguments.value!.previousEmailId, @@ -1309,7 +1312,7 @@ class ComposerController extends BaseController if (composerArguments.value == null || mailboxDashBoardController.sessionCurrent == null || mailboxDashBoardController.accountId.value == null || - mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleDrafts] == null + getDraftMailboxIdForComposer() == null ) { log('ComposerController::handleClickSaveAsDraftsButton: SESSION or ACCOUNT_ID or ARGUMENTS is NULL'); _saveToDraftButtonState = ButtonState.enabled; @@ -2309,7 +2312,7 @@ class ComposerController extends BaseController if (composerArguments.value == null || mailboxDashBoardController.sessionCurrent == null || mailboxDashBoardController.accountId.value == null || - mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleDrafts] == null + getDraftMailboxIdForComposer() == null ) { log('ComposerController::_handleSaveMessageToDraft: SESSION or ACCOUNT_ID or ARGUMENTS is NULL'); _closeComposerButtonState = ButtonState.enabled; @@ -2381,8 +2384,8 @@ class ComposerController extends BaseController identity: identitySelected.value, attachments: uploadController.attachmentsUploaded, inlineAttachments: uploadController.mapInlineAttachments, - sentMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleSent], - draftsMailboxId: mailboxDashBoardController.mapDefaultMailboxIdByRole[PresentationMailbox.roleDrafts], + sentMailboxId: getSentMailboxIdForComposer(), + draftsMailboxId: getDraftMailboxIdForComposer(), draftsEmailId: draftEmailId, answerForwardEmailId: composerArguments.value!.presentationEmail?.id, unsubscribeEmailId: composerArguments.value!.previousEmailId, diff --git a/lib/features/composer/presentation/extensions/get_draft_mailbox_id_for_composer_extension.dart b/lib/features/composer/presentation/extensions/get_draft_mailbox_id_for_composer_extension.dart new file mode 100644 index 000000000..f6915423f --- /dev/null +++ b/lib/features/composer/presentation/extensions/get_draft_mailbox_id_for_composer_extension.dart @@ -0,0 +1,22 @@ +import 'package:collection/collection.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:model/extensions/presentation_mailbox_extension.dart'; +import 'package:model/mailbox/presentation_mailbox.dart'; +import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; + +extension GetDraftMailboxIdForComposerExtension on ComposerController { + MailboxId? getDraftMailboxIdForComposer() { + final defaultDraftsMailbox = mailboxDashBoardController.mapDefaultMailboxIdByRole[ + PresentationMailbox.roleDrafts + ]; + final lowercaseDraftsRole = PresentationMailbox.roleDrafts.value.toLowerCase(); + + return mailboxDashBoardController.mapMailboxById.entries + .firstWhereOrNull((entry) { + final mailbox = entry.value; + return mailbox.emailTeamMailBoxes == identitySelected.value?.email && + mailbox.name?.name.toLowerCase() == lowercaseDraftsRole; + }) + ?.key ?? defaultDraftsMailbox; + } +} \ No newline at end of file diff --git a/lib/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart b/lib/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart new file mode 100644 index 000000000..5b860fc4b --- /dev/null +++ b/lib/features/composer/presentation/extensions/get_outbox_mailbox_id_for_composer_extension.dart @@ -0,0 +1,22 @@ +import 'package:collection/collection.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:model/extensions/presentation_mailbox_extension.dart'; +import 'package:model/mailbox/presentation_mailbox.dart'; +import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; + +extension GetOutboxMailboxIdForComposerExtension on ComposerController { + MailboxId? getOutboxMailboxIdForComposer() { + final defaultOutboxMailbox = mailboxDashBoardController.mapDefaultMailboxIdByRole[ + PresentationMailbox.roleOutbox + ]; + final lowercaseOutboxRole = PresentationMailbox.roleOutbox.value.toLowerCase(); + + return mailboxDashBoardController.mapMailboxById.entries + .firstWhereOrNull((entry) { + final mailbox = entry.value; + return mailbox.emailTeamMailBoxes == identitySelected.value?.email && + mailbox.name?.name.toLowerCase() == lowercaseOutboxRole; + }) + ?.key ?? defaultOutboxMailbox; + } +} \ No newline at end of file diff --git a/lib/features/composer/presentation/extensions/get_sent_mailbox_id_for_composer_extension.dart b/lib/features/composer/presentation/extensions/get_sent_mailbox_id_for_composer_extension.dart new file mode 100644 index 000000000..48554f300 --- /dev/null +++ b/lib/features/composer/presentation/extensions/get_sent_mailbox_id_for_composer_extension.dart @@ -0,0 +1,21 @@ +import 'package:collection/collection.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:model/model.dart'; +import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart'; + +extension GetSentMailboxIdForComposerExtension on ComposerController { + MailboxId? getSentMailboxIdForComposer() { + final defaultSentMailbox = mailboxDashBoardController.mapDefaultMailboxIdByRole[ + PresentationMailbox.roleSent + ]; + final lowercaseSentRole = PresentationMailbox.roleSent.value.toLowerCase(); + + return mailboxDashBoardController.mapMailboxById.entries + .firstWhereOrNull((entry) { + final mailbox = entry.value; + return mailbox.emailTeamMailBoxes == identitySelected.value?.email && + mailbox.name?.name.toLowerCase() == lowercaseSentRole; + }) + ?.key ?? defaultSentMailbox; + } +} \ No newline at end of file diff --git a/test/features/composer/presentation/composer_controller_test.dart b/test/features/composer/presentation/composer_controller_test.dart index 307fe2156..a2c8fee21 100644 --- a/test/features/composer/presentation/composer_controller_test.dart +++ b/test/features/composer/presentation/composer_controller_test.dart @@ -127,6 +127,9 @@ class MockMailboxDashBoardController extends Mock implements MailboxDashBoardCon @override int get minInputLengthAutocomplete => AppConfig.defaultMinInputLengthAutocomplete; + + @override + Map get mapMailboxById => {}; } @GenerateNiceMocks([