TF-4392 [Team Mailbox] Auto save draft email team mailbox when edit

This commit is contained in:
dab246
2026-03-30 16:16:29 +07:00
committed by Dat H. Pham
parent 9feef8da99
commit beb323874b
7 changed files with 53 additions and 31 deletions
@@ -1,20 +1,30 @@
import 'package:collection/collection.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/email/email_action_type.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 savedDraftMailboxId = composerArguments.value?.savedDraftMailboxId;
if (currentEmailActionType == EmailActionType.editDraft &&
savedDraftMailboxId != null) {
return savedDraftMailboxId;
}
final defaultDraftsMailbox = mailboxDashBoardController.mapDefaultMailboxIdByRole[
PresentationMailbox.roleDrafts
];
final lowercaseDraftsRole = PresentationMailbox.roleDrafts.value.toLowerCase();
final identityEmail = identitySelected.value?.email;
return mailboxDashBoardController.mapMailboxById.entries
.firstWhereOrNull((entry) {
if (identityEmail == null) return false;
final mailbox = entry.value;
return mailbox.emailTeamMailBoxes == identitySelected.value?.email &&
return mailbox.emailTeamMailBoxes == identityEmail &&
mailbox.name?.name.toLowerCase() == lowercaseDraftsRole;
})
?.key ?? defaultDraftsMailbox;
@@ -39,6 +39,7 @@ class ComposerArguments extends RouterArguments {
final EmailActionType? savedActionType;
final EmailId? savedEmailDraftId;
final EmailId? savedEmailTemplateId;
final MailboxId? savedDraftMailboxId;
ComposerArguments({
this.emailActionType = EmailActionType.compose,
@@ -68,6 +69,7 @@ class ComposerArguments extends RouterArguments {
this.savedActionType,
this.savedEmailDraftId,
this.savedEmailTemplateId,
this.savedDraftMailboxId,
});
factory ComposerArguments.fromSendingEmail(SendingEmail sendingEmail) =>
@@ -109,10 +111,13 @@ class ComposerArguments extends RouterArguments {
bcc: bcc,
);
factory ComposerArguments.editDraftEmail(PresentationEmail presentationEmail) =>
ComposerArguments(
factory ComposerArguments.editDraftEmail({
required PresentationEmail presentationEmail,
required MailboxId savedDraftMailboxId,
}) => ComposerArguments(
emailActionType: EmailActionType.editDraft,
presentationEmail: presentationEmail,
savedDraftMailboxId: savedDraftMailboxId,
);
factory ComposerArguments.editAsNewEmail(
@@ -265,6 +270,7 @@ class ComposerArguments extends RouterArguments {
savedActionType,
savedEmailDraftId,
sendingEmailActionType,
savedDraftMailboxId,
];
ComposerArguments copyWith({
@@ -295,6 +301,7 @@ class ComposerArguments extends RouterArguments {
EmailActionType? savedActionType,
EmailId? savedEmailDraftId,
EmailId? savedEmailTemplateId,
MailboxId? savedDraftMailboxId,
}) {
return ComposerArguments(
emailActionType: emailActionType ?? this.emailActionType,
@@ -324,6 +331,7 @@ class ComposerArguments extends RouterArguments {
savedActionType: savedActionType ?? this.savedActionType,
savedEmailDraftId: savedEmailDraftId ?? this.savedEmailDraftId,
savedEmailTemplateId: savedEmailTemplateId ?? this.savedEmailTemplateId,
savedDraftMailboxId: savedDraftMailboxId ?? this.savedDraftMailboxId,
);
}
}
@@ -14,11 +14,9 @@ extension GetTrashMailboxIdAndPathExtension on MailboxDashBoardController {
trashPath: null as String?,
);
final mailbox = selectedMailbox.value ?? emailMailbox;
if (emailMailbox.isPersonal) return defaultResult;
if (mailbox.isPersonal) return defaultResult;
final namespace = mailbox.namespace;
final namespace = emailMailbox.namespace;
if (namespace == null) return defaultResult;
final trashId = findDefaultMailboxIdInTeamMailbox(
@@ -924,7 +924,10 @@ class SearchEmailController extends BaseController
switch(actionType) {
case EmailActionType.preview:
if (mailboxContain?.isDrafts == true) {
editDraftEmail(selectedEmail);
editDraftEmail(
presentationEmail: selectedEmail,
draftMailboxId: mailboxContain!.id,
);
} else {
previewEmail(selectedEmail);
}
@@ -9,6 +9,7 @@ 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:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/email/email_action_type.dart';
import 'package:model/email/mark_star_action.dart';
import 'package:model/email/presentation_email.dart';
@@ -41,8 +42,16 @@ mixin EmailActionController {
final responsiveUtils = Get.find<ResponsiveUtils>();
final imagePaths = Get.find<ImagePaths>();
void editDraftEmail(PresentationEmail presentationEmail) {
mailboxDashBoardController.openComposer(ComposerArguments.editDraftEmail(presentationEmail));
void editDraftEmail({
required PresentationEmail presentationEmail,
required MailboxId draftMailboxId,
}) {
mailboxDashBoardController.openComposer(
ComposerArguments.editDraftEmail(
presentationEmail: presentationEmail,
savedDraftMailboxId: draftMailboxId,
),
);
}
void editAsNewEmail(
@@ -1337,7 +1337,10 @@ class ThreadController extends BaseController with EmailActionController {
switch(actionType) {
case EmailActionType.preview:
if (mailboxContain?.isDrafts == true) {
editDraftEmail(selectedEmail);
editDraftEmail(
presentationEmail: selectedEmail,
draftMailboxId: mailboxContain!.id,
);
} else if (mailboxContain?.isTemplates == true) {
editAsNewEmail(selectedEmail, savedEmailTemplateId: selectedEmail.id);
} else {
@@ -66,34 +66,25 @@ void main() {
);
test(
'SHOULD return default trash id with null path '
'WHEN selectedMailbox is personal',
'SHOULD return team trash id '
'WHEN emailMailbox is team mailbox even if selectedMailbox is personal',
() {
when(mockDashBoardController.selectedMailbox)
.thenReturn(Rxn(personalMailbox));
when(mockDashBoardController.findDefaultMailboxIdInTeamMailbox(
namespace: teamNamespace,
mailboxName: PresentationMailbox.trashRole,
)).thenReturn(teamTrashId);
when(mockDashBoardController.getTeamMailboxNodePathWithSeparator(
mailboxId: teamTrashId,
)).thenReturn('Team/Trash');
final result = mockDashBoardController.getTrashMailboxIdAndPath(
teamMailbox,
);
expect(result.trashId, equals(defaultTrashId));
expect(result.trashPath, isNull);
},
);
test(
'SHOULD use selectedMailbox over emailMailbox '
'WHEN selectedMailbox is not null',
() {
when(mockDashBoardController.selectedMailbox)
.thenReturn(Rxn(personalMailbox));
final result = mockDashBoardController.getTrashMailboxIdAndPath(
teamMailbox,
);
expect(result.trashId, equals(defaultTrashId));
expect(result.trashPath, isNull);
expect(result.trashId, equals(teamTrashId));
expect(result.trashPath, equals('Team/Trash'));
},
);