mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-23 18:30:20 +01:00
Add message editing feature.
This commit is contained in:
@@ -88,7 +88,7 @@ import org.thoughtcrime.securesms.util.Base64
|
||||
import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry
|
||||
import org.thoughtcrime.securesms.util.LinkUtil
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.RemoteDeleteUtil
|
||||
import org.thoughtcrime.securesms.util.MessageConstraintsUtil
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.isStory
|
||||
import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata
|
||||
@@ -317,7 +317,7 @@ object DataMessageProcessor {
|
||||
* Inserts an expiration update if the message timer doesn't match the thread timer.
|
||||
*/
|
||||
@Throws(StorageFailedException::class)
|
||||
private fun handlePossibleExpirationUpdate(
|
||||
fun handlePossibleExpirationUpdate(
|
||||
envelope: Envelope,
|
||||
metadata: EnvelopeMetadata,
|
||||
senderRecipientId: RecipientId,
|
||||
@@ -482,7 +482,7 @@ object DataMessageProcessor {
|
||||
return null
|
||||
}
|
||||
|
||||
val targetMessageId = MessageId(targetMessage.id)
|
||||
val targetMessageId = (targetMessage as? MediaMmsMessageRecord)?.latestRevisionId ?: MessageId(targetMessage.id)
|
||||
|
||||
if (isRemove) {
|
||||
SignalDatabase.reactions.deleteReaction(targetMessageId, senderRecipientId)
|
||||
@@ -502,7 +502,7 @@ object DataMessageProcessor {
|
||||
val targetSentTimestamp: Long = message.delete.targetSentTimestamp
|
||||
val targetMessage: MessageRecord? = SignalDatabase.messages.getMessageFor(targetSentTimestamp, senderRecipientId)
|
||||
|
||||
return if (targetMessage != null && RemoteDeleteUtil.isValidReceive(targetMessage, senderRecipientId, envelope.serverTimestamp)) {
|
||||
return if (targetMessage != null && MessageConstraintsUtil.isValidRemoteDeleteReceive(targetMessage, senderRecipientId, envelope.serverTimestamp)) {
|
||||
SignalDatabase.messages.markAsRemoteDelete(targetMessage.id)
|
||||
if (targetMessage.isStory()) {
|
||||
SignalDatabase.messages.deleteRemotelyDeletedStory(targetMessage.id)
|
||||
@@ -944,7 +944,7 @@ object DataMessageProcessor {
|
||||
GroupCallPeekJob.enqueue(groupRecipientId)
|
||||
}
|
||||
|
||||
private fun notifyTypingStoppedFromIncomingMessage(context: Context, senderRecipient: Recipient, threadRecipientId: RecipientId, device: Int) {
|
||||
fun notifyTypingStoppedFromIncomingMessage(context: Context, senderRecipient: Recipient, threadRecipientId: RecipientId, device: Int) {
|
||||
val threadId = SignalDatabase.threads.getThreadIdIfExistsFor(threadRecipientId)
|
||||
|
||||
if (threadId > 0 && TextSecurePreferences.isTypingIndicatorsEnabled(context)) {
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package org.thoughtcrime.securesms.messages
|
||||
|
||||
import android.content.Context
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.signal.core.util.orNull
|
||||
import org.thoughtcrime.securesms.database.MessageTable.InsertResult
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
||||
import org.thoughtcrime.securesms.database.model.toBodyRangeList
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.jobs.PushProcessEarlyMessagesJob
|
||||
import org.thoughtcrime.securesms.jobs.SendDeliveryReceiptJob
|
||||
import org.thoughtcrime.securesms.messages.MessageContentProcessorV2.Companion.log
|
||||
import org.thoughtcrime.securesms.messages.MessageContentProcessorV2.Companion.warn
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.groupId
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isMediaMessage
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toPointers
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.QuoteModel
|
||||
import org.thoughtcrime.securesms.notifications.v2.ConversationId.Companion.forConversation
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage
|
||||
import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.MessageConstraintsUtil
|
||||
import org.thoughtcrime.securesms.util.hasAudio
|
||||
import org.thoughtcrime.securesms.util.hasSharedContact
|
||||
import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.DataMessage
|
||||
import java.util.Optional
|
||||
|
||||
object EditMessageProcessor {
|
||||
fun process(
|
||||
context: Context,
|
||||
senderRecipient: Recipient,
|
||||
threadRecipient: Recipient,
|
||||
envelope: SignalServiceProtos.Envelope,
|
||||
content: SignalServiceProtos.Content,
|
||||
metadata: EnvelopeMetadata,
|
||||
earlyMessageCacheEntry: EarlyMessageCacheEntry?
|
||||
) {
|
||||
val editMessage = content.editMessage
|
||||
|
||||
log(envelope.timestamp, "[handleEditMessage] Edit message for " + editMessage.targetSentTimestamp)
|
||||
|
||||
var targetMessage: MediaMmsMessageRecord? = SignalDatabase.messages.getMessageFor(editMessage.targetSentTimestamp, senderRecipient.id) as MediaMmsMessageRecord
|
||||
val targetThreadRecipient: Recipient? = if (targetMessage != null) SignalDatabase.threads.getRecipientForThreadId(targetMessage.threadId) else null
|
||||
|
||||
if (targetMessage == null || targetThreadRecipient == null) {
|
||||
warn(envelope.timestamp, "[handleEditMessage] Could not find matching message! timestamp: ${editMessage.targetSentTimestamp} author: ${senderRecipient.id}")
|
||||
|
||||
if (earlyMessageCacheEntry != null) {
|
||||
ApplicationDependencies.getEarlyMessageCache().store(senderRecipient.id, editMessage.targetSentTimestamp, earlyMessageCacheEntry)
|
||||
PushProcessEarlyMessagesJob.enqueue()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
val message = editMessage.dataMessage
|
||||
val isMediaMessage = message.isMediaMessage
|
||||
val groupId: GroupId.V2? = message.groupV2.groupId
|
||||
|
||||
val originalMessage = targetMessage.originalMessageId?.let { SignalDatabase.messages.getMessageRecord(it.id) } ?: targetMessage
|
||||
val validTiming = MessageConstraintsUtil.isValidEditMessageReceive(originalMessage, senderRecipient, envelope.serverTimestamp)
|
||||
val validAuthor = senderRecipient.id == originalMessage.fromRecipient.id
|
||||
val validGroup = groupId == targetThreadRecipient.groupId.orNull()
|
||||
val validTarget = !originalMessage.isViewOnce && !originalMessage.hasAudio() && !originalMessage.hasSharedContact()
|
||||
|
||||
if (!validTiming || !validAuthor || !validGroup || !validTarget) {
|
||||
warn(envelope.timestamp, "[handleEditMessage] Invalid message edit! editTime: ${envelope.serverTimestamp}, targetTime: ${originalMessage.serverTimestamp}, editAuthor: ${senderRecipient.id}, targetAuthor: ${originalMessage.fromRecipient.id}, editThread: ${threadRecipient.id}, targetThread: ${targetThreadRecipient.id}, validity: (timing: $validTiming, author: $validAuthor, group: $validGroup, target: $validTarget)")
|
||||
return
|
||||
}
|
||||
|
||||
if (groupId != null && MessageContentProcessorV2.handleGv2PreProcessing(context, envelope.timestamp, content, metadata, groupId, message.groupV2, senderRecipient)) {
|
||||
warn(envelope.timestamp, "[handleEditMessage] Group processor indicated we should ignore this.")
|
||||
return
|
||||
}
|
||||
|
||||
DataMessageProcessor.notifyTypingStoppedFromIncomingMessage(context, senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
|
||||
|
||||
targetMessage = targetMessage.withAttachments(context, SignalDatabase.attachments.getAttachmentsForMessage(targetMessage.id))
|
||||
|
||||
val insertResult: InsertResult? = if (isMediaMessage || targetMessage.quote != null || targetMessage.slideDeck.slides.isNotEmpty()) {
|
||||
handleEditMediaMessage(senderRecipient.id, groupId, envelope, metadata, message, targetMessage)
|
||||
} else {
|
||||
handleEditTextMessage(senderRecipient.id, groupId, envelope, metadata, message, targetMessage)
|
||||
}
|
||||
|
||||
if (insertResult != null) {
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
ApplicationDependencies.getJobManager().add(SendDeliveryReceiptJob(senderRecipient.id, message.timestamp, MessageId(insertResult.messageId)))
|
||||
}
|
||||
|
||||
if (targetMessage.expireStarted > 0) {
|
||||
ApplicationDependencies.getExpiringMessageManager()
|
||||
.scheduleDeletion(
|
||||
insertResult.messageId,
|
||||
true,
|
||||
targetMessage.expireStarted,
|
||||
targetMessage.expiresIn
|
||||
)
|
||||
}
|
||||
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context, forConversation(insertResult.threadId))
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleEditMediaMessage(
|
||||
senderRecipientId: RecipientId,
|
||||
groupId: GroupId.V2?,
|
||||
envelope: SignalServiceProtos.Envelope,
|
||||
metadata: EnvelopeMetadata,
|
||||
message: DataMessage,
|
||||
targetMessage: MediaMmsMessageRecord
|
||||
): InsertResult? {
|
||||
val messageRanges: BodyRangeList? = message.bodyRangesList.filter { it.hasStyle() }.toList().toBodyRangeList()
|
||||
val targetQuote = targetMessage.quote
|
||||
val quote: QuoteModel? = if (targetQuote != null && message.hasQuote()) {
|
||||
QuoteModel(
|
||||
targetQuote.id,
|
||||
targetQuote.author,
|
||||
targetQuote.displayText.toString(),
|
||||
targetQuote.isOriginalMissing,
|
||||
emptyList(),
|
||||
null,
|
||||
targetQuote.quoteType,
|
||||
null
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val attachments = message.attachmentsList.toPointers()
|
||||
attachments.filter {
|
||||
MediaUtil.SlideType.LONG_TEXT == MediaUtil.getSlideTypeFromContentType(it.contentType)
|
||||
}
|
||||
val mediaMessage = IncomingMediaMessage(
|
||||
from = senderRecipientId,
|
||||
sentTimeMillis = message.timestamp,
|
||||
serverTimeMillis = envelope.serverTimestamp,
|
||||
receivedTimeMillis = targetMessage.receiptTimestamp,
|
||||
expiresIn = targetMessage.expiresIn,
|
||||
isViewOnce = message.isViewOnce,
|
||||
isUnidentified = metadata.sealedSender,
|
||||
body = message.body,
|
||||
groupId = groupId,
|
||||
attachments = attachments,
|
||||
quote = quote,
|
||||
sharedContacts = emptyList(),
|
||||
linkPreviews = DataMessageProcessor.getLinkPreviews(message.previewList, message.body ?: "", false),
|
||||
mentions = DataMessageProcessor.getMentions(message.bodyRangesList),
|
||||
serverGuid = envelope.serverGuid,
|
||||
messageRanges = messageRanges,
|
||||
isPushMessage = true
|
||||
)
|
||||
|
||||
return SignalDatabase.messages.insertEditMessageInbox(-1, mediaMessage, targetMessage).orNull()
|
||||
}
|
||||
|
||||
private fun handleEditTextMessage(
|
||||
senderRecipientId: RecipientId,
|
||||
groupId: GroupId.V2?,
|
||||
envelope: SignalServiceProtos.Envelope,
|
||||
metadata: EnvelopeMetadata,
|
||||
message: DataMessage,
|
||||
targetMessage: MediaMmsMessageRecord
|
||||
): InsertResult? {
|
||||
var textMessage = IncomingTextMessage(
|
||||
senderRecipientId,
|
||||
metadata.sourceDeviceId,
|
||||
envelope.timestamp,
|
||||
envelope.timestamp,
|
||||
targetMessage.receiptTimestamp,
|
||||
message.body,
|
||||
Optional.ofNullable(groupId),
|
||||
targetMessage.expiresIn,
|
||||
metadata.sealedSender,
|
||||
envelope.serverGuid
|
||||
)
|
||||
|
||||
textMessage = IncomingEncryptedMessage(textMessage, message.body)
|
||||
|
||||
return SignalDatabase.messages.insertEditMessageInbox(textMessage, targetMessage).orNull()
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEditMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceStoryMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceStoryMessageRecipient;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceTypingMessage;
|
||||
@@ -94,29 +95,15 @@ public final class GroupSendUtil {
|
||||
@NonNull MessageId messageId,
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
boolean urgent,
|
||||
boolean isForStory)
|
||||
boolean isForStory,
|
||||
@Nullable SignalServiceEditMessage editMessage)
|
||||
throws IOException, UntrustedIdentityException
|
||||
{
|
||||
Preconditions.checkArgument(groupId == null || distributionListId == null, "Cannot supply both a groupId and a distributionListId!");
|
||||
|
||||
DistributionId distributionId = groupId != null ? getDistributionId(groupId) : getDistributionId(distributionListId);
|
||||
|
||||
return sendMessage(context, groupId, distributionId, messageId, allTargets, isRecipientUpdate, isForStory, DataSendOperation.resendable(message, contentHint, messageId, urgent, isForStory), null);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public static List<SendMessageResult> sendResendableStoryRelatedMessage(@NonNull Context context,
|
||||
@Nullable GroupId.V2 groupId,
|
||||
@NonNull DistributionListId distributionListId,
|
||||
@NonNull List<Recipient> allTargets,
|
||||
boolean isRecipientUpdate,
|
||||
ContentHint contentHint,
|
||||
@NonNull MessageId messageId,
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
boolean urgent)
|
||||
throws IOException, UntrustedIdentityException
|
||||
{
|
||||
return sendMessage(context, groupId, getDistributionId(distributionListId), messageId, allTargets, isRecipientUpdate, true, DataSendOperation.resendable(message, contentHint, messageId, urgent, true), null);
|
||||
return sendMessage(context, groupId, distributionId, messageId, allTargets, isRecipientUpdate, isForStory, DataSendOperation.resendable(message, contentHint, messageId, urgent, isForStory, editMessage), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -480,22 +467,24 @@ public final class GroupSendUtil {
|
||||
private final boolean resendable;
|
||||
private final boolean urgent;
|
||||
private final boolean isForStory;
|
||||
private final SignalServiceEditMessage editMessage;
|
||||
|
||||
public static DataSendOperation resendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, @NonNull MessageId relatedMessageId, boolean urgent, boolean isForStory) {
|
||||
return new DataSendOperation(message, contentHint, true, relatedMessageId, urgent, isForStory);
|
||||
public static DataSendOperation resendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, @NonNull MessageId relatedMessageId, boolean urgent, boolean isForStory, @Nullable SignalServiceEditMessage editMessage) {
|
||||
return new DataSendOperation(editMessage != null ? editMessage.getDataMessage() : message, contentHint, true, relatedMessageId, urgent, isForStory, editMessage);
|
||||
}
|
||||
|
||||
public static DataSendOperation unresendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean urgent) {
|
||||
return new DataSendOperation(message, contentHint, false, null, urgent, false);
|
||||
return new DataSendOperation(message, contentHint, false, null, urgent, false, null);
|
||||
}
|
||||
|
||||
private DataSendOperation(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean resendable, @Nullable MessageId relatedMessageId, boolean urgent, boolean isForStory) {
|
||||
private DataSendOperation(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean resendable, @Nullable MessageId relatedMessageId, boolean urgent, boolean isForStory, @Nullable SignalServiceEditMessage editMessage) {
|
||||
this.message = message;
|
||||
this.contentHint = contentHint;
|
||||
this.resendable = resendable;
|
||||
this.relatedMessageId = relatedMessageId;
|
||||
this.urgent = urgent;
|
||||
this.isForStory = isForStory;
|
||||
this.editMessage = editMessage;
|
||||
|
||||
if (resendable && relatedMessageId == null) {
|
||||
throw new IllegalArgumentException("If a message is resendable, it must have a related message ID!");
|
||||
@@ -512,7 +501,7 @@ public final class GroupSendUtil {
|
||||
throws NoSessionException, UntrustedIdentityException, InvalidKeyException, IOException, InvalidRegistrationIdException
|
||||
{
|
||||
SenderKeyGroupEvents listener = relatedMessageId != null ? new SenderKeyMetricEventListener(relatedMessageId.getId()) : SenderKeyGroupEvents.EMPTY;
|
||||
return messageSender.sendGroupDataMessage(distributionId, targets, access, isRecipientUpdate, contentHint, message, listener, urgent, isForStory, partialListener);
|
||||
return messageSender.sendGroupDataMessage(distributionId, targets, access, isRecipientUpdate, contentHint, message, listener, urgent, isForStory, editMessage, partialListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -527,8 +516,14 @@ public final class GroupSendUtil {
|
||||
{
|
||||
// PniSignatures are only needed for 1:1 messages, but some message jobs use the GroupSendUtil methods to send 1:1
|
||||
if (targets.size() == 1 && relatedMessageId == null) {
|
||||
Recipient targetRecipient = targetRecipients.get(0);
|
||||
SendMessageResult result = messageSender.sendDataMessage(targets.get(0), access.get(0), contentHint, message, SignalServiceMessageSender.IndividualSendEvents.EMPTY, urgent, targetRecipient.needsPniSignature());
|
||||
Recipient targetRecipient = targetRecipients.get(0);
|
||||
SendMessageResult result;
|
||||
|
||||
if (editMessage != null) {
|
||||
result = messageSender.sendEditMessage(targets.get(0), access.get(0), contentHint, message, SignalServiceMessageSender.IndividualSendEvents.EMPTY, urgent, editMessage.getTargetSentTimestamp());
|
||||
} else {
|
||||
result = messageSender.sendDataMessage(targets.get(0), access.get(0), contentHint, message, SignalServiceMessageSender.IndividualSendEvents.EMPTY, urgent, targetRecipient.needsPniSignature());
|
||||
}
|
||||
|
||||
if (targetRecipient.needsPniSignature()) {
|
||||
SignalDatabase.pendingPniSignatureMessages().insertIfNecessary(targetRecipients.get(0).getId(), getSentTimestamp(), result);
|
||||
|
||||
@@ -134,7 +134,7 @@ import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||
import org.thoughtcrime.securesms.util.LinkUtil;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.MessageRecordUtil;
|
||||
import org.thoughtcrime.securesms.util.RemoteDeleteUtil;
|
||||
import org.thoughtcrime.securesms.util.MessageConstraintsUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
@@ -1064,7 +1064,7 @@ public class MessageContentProcessor {
|
||||
|
||||
MessageRecord targetMessage = SignalDatabase.messages().getMessageFor(delete.getTargetSentTimestamp(), senderRecipient.getId());
|
||||
|
||||
if (targetMessage != null && RemoteDeleteUtil.isValidReceive(targetMessage, senderRecipient, content.getServerReceivedTimestamp())) {
|
||||
if (targetMessage != null && MessageConstraintsUtil.isValidRemoteDeleteReceive(targetMessage, senderRecipient.getId(), content.getServerReceivedTimestamp())) {
|
||||
MessageTable db = targetMessage.isMms() ? SignalDatabase.messages() : SignalDatabase.messages();
|
||||
db.markAsRemoteDelete(targetMessage.getId());
|
||||
if (MessageRecordUtil.isStory(targetMessage)) {
|
||||
@@ -2220,7 +2220,8 @@ public class MessageContentProcessor {
|
||||
null,
|
||||
true,
|
||||
bodyRanges,
|
||||
-1);
|
||||
-1,
|
||||
0);
|
||||
|
||||
if (recipient.getExpiresInSeconds() != message.getDataMessage().get().getExpiresInSeconds()) {
|
||||
handleSynchronizeSentExpirationUpdate(message);
|
||||
@@ -2342,7 +2343,8 @@ public class MessageContentProcessor {
|
||||
null,
|
||||
true,
|
||||
bodyRanges,
|
||||
-1);
|
||||
-1,
|
||||
0);
|
||||
|
||||
MessageTable messageTable = SignalDatabase.messages();
|
||||
long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipient);
|
||||
@@ -2441,7 +2443,8 @@ public class MessageContentProcessor {
|
||||
giftBadge.orElse(null),
|
||||
true,
|
||||
bodyRanges,
|
||||
-1);
|
||||
-1,
|
||||
0);
|
||||
|
||||
if (recipient.getExpiresInSeconds() != message.getDataMessage().get().getExpiresInSeconds()) {
|
||||
handleSynchronizeSentExpirationUpdate(message);
|
||||
|
||||
@@ -111,6 +111,8 @@ open class MessageContentProcessorV2(private val context: Context) {
|
||||
getGroupRecipient(content.storyMessage.group, sender)
|
||||
} else if (content.dataMessage.hasGroupContext) {
|
||||
getGroupRecipient(content.dataMessage.groupV2, sender)
|
||||
} else if (content.editMessage.dataMessage.hasGroupContext) {
|
||||
getGroupRecipient(content.editMessage.dataMessage.groupV2, sender)
|
||||
} else {
|
||||
sender
|
||||
}
|
||||
@@ -379,6 +381,21 @@ open class MessageContentProcessorV2(private val context: Context) {
|
||||
content.hasDecryptionErrorMessage() -> {
|
||||
handleRetryReceipt(envelope, metadata, content.decryptionErrorMessage!!.toDecryptionErrorMessage(metadata), senderRecipient)
|
||||
}
|
||||
content.hasEditMessage() -> {
|
||||
if (FeatureFlags.editMessageReceiving()) {
|
||||
EditMessageProcessor.process(
|
||||
context,
|
||||
senderRecipient,
|
||||
threadRecipient,
|
||||
envelope,
|
||||
content,
|
||||
metadata,
|
||||
if (processingEarlyContent) null else EarlyMessageCacheEntry(envelope, content, metadata, serverDeliveredTimestamp)
|
||||
)
|
||||
} else {
|
||||
warn(envelope.timestamp, "Got message edit, but processing is disabled")
|
||||
}
|
||||
}
|
||||
content.hasSenderKeyDistributionMessage() || content.hasPniSignatureMessage() -> {
|
||||
// Already handled, here in order to prevent unrecognized message log
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user