TF-1767 Fix Reply/Forward original message should be marked, not the sent one
(cherry picked from commit 827c6537cbad268dac4860fb0c57714811ed44e1)
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
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/identities/identity.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.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 {
|
class EmailRequest with EquatableMixin {
|
||||||
|
|
||||||
final Email email;
|
final Email email;
|
||||||
final Id submissionCreateId;
|
|
||||||
final MailboxId? sentMailboxId;
|
final MailboxId? sentMailboxId;
|
||||||
final EmailId? emailIdDestroyed;
|
final EmailId? emailIdDestroyed;
|
||||||
|
final EmailId? emailIdAnsweredOrForwarded;
|
||||||
final Identity? identity;
|
final Identity? identity;
|
||||||
final EmailActionType? emailActionType;
|
final EmailActionType? emailActionType;
|
||||||
|
|
||||||
EmailRequest(this.email, this.submissionCreateId, {
|
EmailRequest(
|
||||||
|
this.email, {
|
||||||
this.sentMailboxId,
|
this.sentMailboxId,
|
||||||
this.identity,
|
this.identity,
|
||||||
this.emailIdDestroyed,
|
this.emailIdDestroyed,
|
||||||
|
this.emailIdAnsweredOrForwarded,
|
||||||
this.emailActionType
|
this.emailActionType
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
email,
|
email,
|
||||||
submissionCreateId,
|
|
||||||
sentMailboxId,
|
sentMailboxId,
|
||||||
identity,
|
identity,
|
||||||
emailIdDestroyed,
|
emailIdDestroyed,
|
||||||
|
emailIdAnsweredOrForwarded,
|
||||||
emailActionType
|
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) {
|
if (arguments != null && accountId != null && userProfile != null && session != null) {
|
||||||
final email = await _generateEmail(context, userProfile, outboxMailboxId: outboxMailboxId);
|
final email = await _generateEmail(context, userProfile, outboxMailboxId: outboxMailboxId);
|
||||||
final submissionCreateId = Id(_uuid.v1());
|
|
||||||
final emailRequest = EmailRequest(
|
final emailRequest = EmailRequest(
|
||||||
email,
|
email,
|
||||||
submissionCreateId,
|
|
||||||
sentMailboxId: sentMailboxId,
|
sentMailboxId: sentMailboxId,
|
||||||
identity: identitySelected.value,
|
identity: identitySelected.value,
|
||||||
emailIdDestroyed: arguments.emailActionType == EmailActionType.edit
|
emailIdDestroyed: arguments.emailActionType == EmailActionType.edit
|
||||||
? arguments.presentationEmail?.id
|
? arguments.presentationEmail?.id
|
||||||
: null,
|
: null,
|
||||||
|
emailIdAnsweredOrForwarded: arguments.presentationEmail?.id,
|
||||||
emailActionType: arguments.emailActionType
|
emailActionType: arguments.emailActionType
|
||||||
);
|
);
|
||||||
final mailboxRequest = outboxMailboxId == null
|
final mailboxRequest = outboxMailboxId == null
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:dio/dio.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/capability/core_capability.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/error/set_error.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/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/patch_object.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/properties/properties.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_id.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/reference_prefix.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/core/session/session.dart';
|
||||||
import 'package:jmap_dart_client/jmap/jmap_request.dart';
|
import 'package:jmap_dart_client/jmap/jmap_request.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
|
||||||
@@ -141,32 +144,48 @@ class EmailAPI with HandleSetErrorMixin {
|
|||||||
final setEmailMethod = SetEmailMethod(accountId)
|
final setEmailMethod = SetEmailMethod(accountId)
|
||||||
..addCreate(idCreateMethod, emailNeedsToBeCreated);
|
..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)
|
final setEmailSubmissionMethod = SetEmailSubmissionMethod(accountId)
|
||||||
..addCreate(
|
..addCreate(submissionCreateId, emailSubmission)
|
||||||
emailRequest.submissionCreateId,
|
..addOnSuccessUpdateEmail(mapEmailSubmissionUpdated);
|
||||||
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
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
|
final setEmailInvocation = requestBuilder.invocation(setEmailMethod);
|
||||||
final setEmailSubmissionInvocation = requestBuilder.invocation(setEmailSubmissionMethod);
|
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
|
final capabilities = setEmailSubmissionMethod.requiredCapabilities
|
||||||
.toCapabilitiesSupportTeamMailboxes(session, accountId);
|
.toCapabilitiesSupportTeamMailboxes(session, accountId);
|
||||||
|
|
||||||
@@ -184,11 +203,18 @@ class EmailAPI with HandleSetErrorMixin {
|
|||||||
SetEmailSubmissionResponse.deserialize,
|
SetEmailSubmissionResponse.deserialize,
|
||||||
methodName: setEmailInvocation.methodName);
|
methodName: setEmailInvocation.methodName);
|
||||||
|
|
||||||
|
if (markAsAnsweredOrForwardedInvocation != null) {
|
||||||
|
markAsAnsweredOrForwardedSetResponse = response.parse<SetEmailResponse>(
|
||||||
|
markAsAnsweredOrForwardedInvocation.methodCallId,
|
||||||
|
SetEmailResponse.deserialize);
|
||||||
|
}
|
||||||
|
|
||||||
final emailCreated = setEmailResponse?.created?[idCreateMethod];
|
final emailCreated = setEmailResponse?.created?[idCreateMethod];
|
||||||
final listEntriesErrors = _handleSetEmailResponse(
|
final listEntriesErrors = _handleSetEmailResponse([
|
||||||
response: setEmailResponse,
|
setEmailResponse,
|
||||||
submissionResponse: setEmailSubmissionResponse
|
setEmailSubmissionResponse,
|
||||||
);
|
markAsAnsweredOrForwardedSetResponse
|
||||||
|
]);
|
||||||
final mapErrors = Map.fromEntries(listEntriesErrors);
|
final mapErrors = Map.fromEntries(listEntriesErrors);
|
||||||
|
|
||||||
if (emailCreated != null && mapErrors.isEmpty) {
|
if (emailCreated != null && mapErrors.isEmpty) {
|
||||||
@@ -198,12 +224,14 @@ class EmailAPI with HandleSetErrorMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MapEntry<Id, SetError>> _handleSetEmailResponse({
|
List<MapEntry<Id, SetError>> _handleSetEmailResponse(List<SetResponse?> listSetResponse) {
|
||||||
SetEmailResponse? response,
|
final listSetResponseNotNull = listSetResponse.whereNotNull().toList();
|
||||||
SetEmailSubmissionResponse? submissionResponse
|
if (listSetResponseNotNull.isEmpty) {
|
||||||
}) {
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
final List<MapEntry<Id, SetError>> remainedErrors = [];
|
final List<MapEntry<Id, SetError>> remainedErrors = [];
|
||||||
if (response != null) {
|
for (var response in listSetResponseNotNull) {
|
||||||
handleSetErrors(
|
handleSetErrors(
|
||||||
notDestroyedError: response.notDestroyed,
|
notDestroyedError: response.notDestroyed,
|
||||||
notUpdatedError: response.notUpdated,
|
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;
|
return remainedErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,7 +445,6 @@ class EmailAPI with HandleSetErrorMixin {
|
|||||||
return listEmailIdRequest.where((emailId) => listUpdated.expand((e) => e).toList().contains(emailId.id)).toList();
|
return listEmailIdRequest.where((emailId) => listUpdated.expand((e) => e).toList().contains(emailId.id)).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<List<Email>> markAsStar(
|
Future<List<Email>> markAsStar(
|
||||||
Session session,
|
Session session,
|
||||||
AccountId accountId,
|
AccountId accountId,
|
||||||
@@ -490,7 +506,7 @@ class EmailAPI with HandleSetErrorMixin {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final emailCreated = setEmailResponse?.created?[idCreateMethod];
|
final emailCreated = setEmailResponse?.created?[idCreateMethod];
|
||||||
final listEntriesErrors = _handleSetEmailResponse(response: setEmailResponse);
|
final listEntriesErrors = _handleSetEmailResponse([setEmailResponse]);
|
||||||
final mapErrors = Map.fromEntries(listEntriesErrors);
|
final mapErrors = Map.fromEntries(listEntriesErrors);
|
||||||
|
|
||||||
if (emailCreated != null && mapErrors.isEmpty) {
|
if (emailCreated != null && mapErrors.isEmpty) {
|
||||||
@@ -554,7 +570,7 @@ class EmailAPI with HandleSetErrorMixin {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final emailUpdated = setEmailResponse?.created?[idCreateMethod];
|
final emailUpdated = setEmailResponse?.created?[idCreateMethod];
|
||||||
final listEntriesErrors = _handleSetEmailResponse(response: setEmailResponse);
|
final listEntriesErrors = _handleSetEmailResponse([setEmailResponse]);
|
||||||
final mapErrors = Map.fromEntries(listEntriesErrors);
|
final mapErrors = Map.fromEntries(listEntriesErrors);
|
||||||
|
|
||||||
if (emailUpdated != null && mapErrors.isEmpty) {
|
if (emailUpdated != null && mapErrors.isEmpty) {
|
||||||
|
|||||||
@@ -19,4 +19,16 @@ extension KeyWordIdentifierExtension on KeyWordIdentifier {
|
|||||||
generatePath(): markStarAction == MarkStarAction.markStar ? true : null
|
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();
|
List<Id> toIds() => map((emailId) => emailId.id).toList();
|
||||||
|
|
||||||
Map<Id, PatchObject> generateMapUpdateObjectMarkAsRead(ReadActions readActions) {
|
Map<Id, PatchObject> generateMapUpdateObjectMarkAsRead(ReadActions readActions) {
|
||||||
final Map<Id, PatchObject> maps = {};
|
return {
|
||||||
forEach((emailId) {
|
for (var emailId in this)
|
||||||
maps[emailId.id] = KeyWordIdentifier.emailSeen.generateReadActionPath(readActions);
|
emailId.id: KeyWordIdentifier.emailSeen.generateReadActionPath(readActions)
|
||||||
});
|
};
|
||||||
return maps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Id, PatchObject> generateMapUpdateObjectMoveToMailbox(MailboxId currentMailboxId, MailboxId destinationMailboxId) {
|
Map<Id, PatchObject> generateMapUpdateObjectMoveToMailbox(MailboxId currentMailboxId, MailboxId destinationMailboxId) {
|
||||||
final Map<Id, PatchObject> maps = {};
|
return {
|
||||||
forEach((emailId) {
|
for (var emailId in this)
|
||||||
maps[emailId.id] = currentMailboxId.generateMoveToMailboxActionPath(destinationMailboxId);
|
emailId.id: currentMailboxId.generateMoveToMailboxActionPath(destinationMailboxId)
|
||||||
});
|
};
|
||||||
return maps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Id, PatchObject> generateMapUpdateObjectMarkAsStar(MarkStarAction markStarAction) {
|
Map<Id, PatchObject> generateMapUpdateObjectMarkAsStar(MarkStarAction markStarAction) {
|
||||||
final Map<Id, PatchObject> maps = {};
|
return {
|
||||||
forEach((emailId) {
|
for (var emailId in this)
|
||||||
maps[emailId.id] = KeyWordIdentifier.emailFlagged.generateMarkStarActionPath(markStarAction);
|
emailId.id: KeyWordIdentifier.emailFlagged.generateMarkStarActionPath(markStarAction)
|
||||||
});
|
};
|
||||||
return maps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Id, PatchObject> generateMapUpdateObjectMarkAsSpam(MailboxId spamMailboxId) {
|
Map<Id, PatchObject> generateMapUpdateObjectMarkAsSpam(MailboxId spamMailboxId) {
|
||||||
final Map<Id, PatchObject> maps = {};
|
return {
|
||||||
forEach((emailId) {
|
for (var emailId in this)
|
||||||
maps[emailId.id] = spamMailboxId.generateActionPath();
|
emailId.id: spamMailboxId.generateActionPath()
|
||||||
});
|
};
|
||||||
return maps;
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user