TF-1767 Fix Reply/Forward original message should be marked, not the sent one

(cherry picked from commit 827c6537cbad268dac4860fb0c57714811ed44e1)
This commit is contained in:
dab246
2023-04-18 15:31:01 +07:00
committed by Dat Vu
parent 00a8d92ec9
commit efc2104933
5 changed files with 111 additions and 72 deletions
@@ -1,6 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
@@ -9,30 +8,33 @@ import 'package:model/email/email_action_type.dart';
class EmailRequest with EquatableMixin {
final Email email;
final Id submissionCreateId;
final MailboxId? sentMailboxId;
final EmailId? emailIdDestroyed;
final EmailId? emailIdAnsweredOrForwarded;
final Identity? identity;
final EmailActionType? emailActionType;
EmailRequest(this.email, this.submissionCreateId, {
EmailRequest(
this.email, {
this.sentMailboxId,
this.identity,
this.emailIdDestroyed,
this.emailIdAnsweredOrForwarded,
this.emailActionType
});
@override
List<Object?> get props => [
email,
submissionCreateId,
sentMailboxId,
identity,
emailIdDestroyed,
emailIdAnsweredOrForwarded,
emailActionType
];
bool get isEmailAnswered => emailActionType == EmailActionType.reply || emailActionType == EmailActionType.replyAll;
bool get isEmailAnswered => emailIdAnsweredOrForwarded != null &&
(emailActionType == EmailActionType.reply || emailActionType == EmailActionType.replyAll);
bool get isEmailForwarded => emailActionType == EmailActionType.forward;
bool get isEmailForwarded => emailIdAnsweredOrForwarded != null && emailActionType == EmailActionType.forward;
}
@@ -807,15 +807,14 @@ class ComposerController extends BaseController {
if (arguments != null && accountId != null && userProfile != null && session != null) {
final email = await _generateEmail(context, userProfile, outboxMailboxId: outboxMailboxId);
final submissionCreateId = Id(_uuid.v1());
final emailRequest = EmailRequest(
email,
submissionCreateId,
sentMailboxId: sentMailboxId,
identity: identitySelected.value,
emailIdDestroyed: arguments.emailActionType == EmailActionType.edit
? arguments.presentationEmail?.id
: null,
emailIdAnsweredOrForwarded: arguments.presentationEmail?.id,
emailActionType: arguments.emailActionType
);
final mailboxRequest = outboxMailboxId == null
+60 -44
View File
@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:collection/collection.dart';
import 'package:core/core.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
@@ -13,10 +14,12 @@ import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart
import 'package:jmap_dart_client/jmap/core/capability/core_capability.dart';
import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/method/response/set_response.dart';
import 'package:jmap_dart_client/jmap/core/patch_object.dart';
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
import 'package:jmap_dart_client/jmap/core/reference_id.dart';
import 'package:jmap_dart_client/jmap/core/reference_prefix.dart';
import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/jmap_request.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
@@ -141,32 +144,48 @@ class EmailAPI with HandleSetErrorMixin {
final setEmailMethod = SetEmailMethod(accountId)
..addCreate(idCreateMethod, emailNeedsToBeCreated);
final setEmailInvocation = requestBuilder.invocation(setEmailMethod);
final submissionCreateId = Id(_uuid.v1());
final mailFrom = Address(emailNeedsToBeCreated.from?.first.email ?? '');
final recipientsList = emailNeedsToBeCreated.getRecipientEmailAddressList()
.map((emailAddress) => Address(emailAddress))
.toSet();
final emailSubmissionId = EmailSubmissionId(ReferenceId(ReferencePrefix.defaultPrefix, submissionCreateId));
Map<EmailSubmissionId, PatchObject> mapEmailSubmissionUpdated = {
emailSubmissionId: PatchObject({
emailRequest.sentMailboxId!.generatePath() : true,
outboxMailboxId!.generatePath() : null,
KeyWordIdentifier.emailSeen.generatePath(): true,
KeyWordIdentifier.emailDraft.generatePath(): null
})
};
final emailSubmission = EmailSubmission(
identityId: emailRequest.identity?.id?.id,
emailId: EmailId(ReferenceId(ReferencePrefix.defaultPrefix, idCreateMethod)),
envelope: Envelope(mailFrom, recipientsList));
final setEmailSubmissionMethod = SetEmailSubmissionMethod(accountId)
..addCreate(
emailRequest.submissionCreateId,
EmailSubmission(
identityId: emailRequest.identity?.id?.id,
emailId: EmailId(ReferenceId(ReferencePrefix.defaultPrefix, idCreateMethod)),
envelope: Envelope(
Address(emailNeedsToBeCreated.from?.first.email ?? ''),
emailNeedsToBeCreated.getRecipientEmailAddressList().map((emailAddress) => Address(emailAddress)).toSet()
)
))
..addOnSuccessUpdateEmail({
EmailSubmissionId(ReferenceId(ReferencePrefix.defaultPrefix, emailRequest.submissionCreateId)): PatchObject({
emailRequest.sentMailboxId!.generatePath() : true,
outboxMailboxId!.generatePath() : null,
KeyWordIdentifier.emailSeen.generatePath(): true,
KeyWordIdentifier.emailDraft.generatePath(): null,
KeyWordIdentifier.emailAnswered.generatePath(): emailRequest.isEmailAnswered ? true : null,
KeyWordIdentifier.emailForwarded.generatePath(): emailRequest.isEmailForwarded ? true : null
})
});
..addCreate(submissionCreateId, emailSubmission)
..addOnSuccessUpdateEmail(mapEmailSubmissionUpdated);
final setEmailInvocation = requestBuilder.invocation(setEmailMethod);
final setEmailSubmissionInvocation = requestBuilder.invocation(setEmailSubmissionMethod);
SetEmailMethod? markAsAnsweredOrForwardedSetMethod;
RequestInvocation? markAsAnsweredOrForwardedInvocation;
SetEmailResponse? markAsAnsweredOrForwardedSetResponse;
if (emailRequest.isEmailAnswered) {
markAsAnsweredOrForwardedSetMethod = SetEmailMethod(accountId)
..addUpdates([emailRequest.emailIdAnsweredOrForwarded!].generateMapUpdateObjectMarkAsAnswered());
markAsAnsweredOrForwardedInvocation = requestBuilder.invocation(markAsAnsweredOrForwardedSetMethod);
} else if (emailRequest.isEmailForwarded) {
markAsAnsweredOrForwardedSetMethod = SetEmailMethod(accountId)
..addUpdates([emailRequest.emailIdAnsweredOrForwarded!].generateMapUpdateObjectMarkAsForwarded());
markAsAnsweredOrForwardedInvocation = requestBuilder.invocation(markAsAnsweredOrForwardedSetMethod);
}
final capabilities = setEmailSubmissionMethod.requiredCapabilities
.toCapabilitiesSupportTeamMailboxes(session, accountId);
@@ -184,11 +203,18 @@ class EmailAPI with HandleSetErrorMixin {
SetEmailSubmissionResponse.deserialize,
methodName: setEmailInvocation.methodName);
if (markAsAnsweredOrForwardedInvocation != null) {
markAsAnsweredOrForwardedSetResponse = response.parse<SetEmailResponse>(
markAsAnsweredOrForwardedInvocation.methodCallId,
SetEmailResponse.deserialize);
}
final emailCreated = setEmailResponse?.created?[idCreateMethod];
final listEntriesErrors = _handleSetEmailResponse(
response: setEmailResponse,
submissionResponse: setEmailSubmissionResponse
);
final listEntriesErrors = _handleSetEmailResponse([
setEmailResponse,
setEmailSubmissionResponse,
markAsAnsweredOrForwardedSetResponse
]);
final mapErrors = Map.fromEntries(listEntriesErrors);
if (emailCreated != null && mapErrors.isEmpty) {
@@ -198,12 +224,14 @@ class EmailAPI with HandleSetErrorMixin {
}
}
List<MapEntry<Id, SetError>> _handleSetEmailResponse({
SetEmailResponse? response,
SetEmailSubmissionResponse? submissionResponse
}) {
List<MapEntry<Id, SetError>> _handleSetEmailResponse(List<SetResponse?> listSetResponse) {
final listSetResponseNotNull = listSetResponse.whereNotNull().toList();
if (listSetResponseNotNull.isEmpty) {
return [];
}
final List<MapEntry<Id, SetError>> remainedErrors = [];
if (response != null) {
for (var response in listSetResponseNotNull) {
handleSetErrors(
notDestroyedError: response.notDestroyed,
notUpdatedError: response.notUpdated,
@@ -214,17 +242,6 @@ class EmailAPI with HandleSetErrorMixin {
}
);
}
if (submissionResponse != null) {
handleSetErrors(
notDestroyedError: submissionResponse.notDestroyed,
notUpdatedError: submissionResponse.notUpdated,
notCreatedError: submissionResponse.notCreated,
unCatchErrorHandler: (setErrorEntry) {
remainedErrors.add(setErrorEntry);
return false;
}
);
}
return remainedErrors;
}
@@ -428,7 +445,6 @@ class EmailAPI with HandleSetErrorMixin {
return listEmailIdRequest.where((emailId) => listUpdated.expand((e) => e).toList().contains(emailId.id)).toList();
}
Future<List<Email>> markAsStar(
Session session,
AccountId accountId,
@@ -490,7 +506,7 @@ class EmailAPI with HandleSetErrorMixin {
);
final emailCreated = setEmailResponse?.created?[idCreateMethod];
final listEntriesErrors = _handleSetEmailResponse(response: setEmailResponse);
final listEntriesErrors = _handleSetEmailResponse([setEmailResponse]);
final mapErrors = Map.fromEntries(listEntriesErrors);
if (emailCreated != null && mapErrors.isEmpty) {
@@ -554,7 +570,7 @@ class EmailAPI with HandleSetErrorMixin {
);
final emailUpdated = setEmailResponse?.created?[idCreateMethod];
final listEntriesErrors = _handleSetEmailResponse(response: setEmailResponse);
final listEntriesErrors = _handleSetEmailResponse([setEmailResponse]);
final mapErrors = Map.fromEntries(listEntriesErrors);
if (emailUpdated != null && mapErrors.isEmpty) {
@@ -19,4 +19,16 @@ extension KeyWordIdentifierExtension on KeyWordIdentifier {
generatePath(): markStarAction == MarkStarAction.markStar ? true : null
});
}
PatchObject generateAnsweredActionPath() {
return PatchObject({
generatePath(): true
});
}
PatchObject generateForwardedActionPath() {
return PatchObject({
generatePath(): true
});
}
}
@@ -10,34 +10,44 @@ extension ListEmailIdExtension on List<EmailId> {
List<Id> toIds() => map((emailId) => emailId.id).toList();
Map<Id, PatchObject> generateMapUpdateObjectMarkAsRead(ReadActions readActions) {
final Map<Id, PatchObject> maps = {};
forEach((emailId) {
maps[emailId.id] = KeyWordIdentifier.emailSeen.generateReadActionPath(readActions);
});
return maps;
return {
for (var emailId in this)
emailId.id: KeyWordIdentifier.emailSeen.generateReadActionPath(readActions)
};
}
Map<Id, PatchObject> generateMapUpdateObjectMoveToMailbox(MailboxId currentMailboxId, MailboxId destinationMailboxId) {
final Map<Id, PatchObject> maps = {};
forEach((emailId) {
maps[emailId.id] = currentMailboxId.generateMoveToMailboxActionPath(destinationMailboxId);
});
return maps;
return {
for (var emailId in this)
emailId.id: currentMailboxId.generateMoveToMailboxActionPath(destinationMailboxId)
};
}
Map<Id, PatchObject> generateMapUpdateObjectMarkAsStar(MarkStarAction markStarAction) {
final Map<Id, PatchObject> maps = {};
forEach((emailId) {
maps[emailId.id] = KeyWordIdentifier.emailFlagged.generateMarkStarActionPath(markStarAction);
});
return maps;
return {
for (var emailId in this)
emailId.id: KeyWordIdentifier.emailFlagged.generateMarkStarActionPath(markStarAction)
};
}
Map<Id, PatchObject> generateMapUpdateObjectMarkAsSpam(MailboxId spamMailboxId) {
final Map<Id, PatchObject> maps = {};
forEach((emailId) {
maps[emailId.id] = spamMailboxId.generateActionPath();
});
return maps;
return {
for (var emailId in this)
emailId.id: spamMailboxId.generateActionPath()
};
}
Map<Id, PatchObject> generateMapUpdateObjectMarkAsAnswered() {
return {
for (var emailId in this)
emailId.id: KeyWordIdentifier.emailAnswered.generateAnsweredActionPath()
};
}
Map<Id, PatchObject> generateMapUpdateObjectMarkAsForwarded() {
return {
for (var emailId in this)
emailId.id: KeyWordIdentifier.emailForwarded.generateForwardedActionPath()
};
}
}