From 33619fe463bf07405f037fe6b9ecd261c76abac7 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 9 Jun 2026 11:50:44 -0400 Subject: [PATCH] Fix IndividualSendJobV2 edit message timestamps. --- .../securesms/jobs/IndividualSendJobV2.kt | 2 +- .../securesms/jobs/IndividualSendJobV2Test.kt | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/IndividualSendJobV2.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/IndividualSendJobV2.kt index 1b255f69bb..93e8e07bec 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/IndividualSendJobV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/IndividualSendJobV2.kt @@ -195,7 +195,7 @@ class IndividualSendJobV2 private constructor(parameters: Parameters, private va Log.i(TAG, "${logPrefix(message.sentTimeMillis)} Sending message. Recipient: ${message.threadRecipient.id}, Thread: $threadId, Attachments: ${buildAttachmentString(message.attachments)}, Editing: ${originalEditedMessage?.dateSent ?: "N/A"}") SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId, message.sentTimeMillis) - return sendMessage(recipient, dataMessage, originalEditedMessage?.timestamp).fold( + return sendMessage(recipient, dataMessage, originalEditedMessage?.dateSent).fold( ifRight = { success -> val content = success.envelopeContent.content.get() diff --git a/app/src/test/java/org/thoughtcrime/securesms/jobs/IndividualSendJobV2Test.kt b/app/src/test/java/org/thoughtcrime/securesms/jobs/IndividualSendJobV2Test.kt index 0beb023942..37c1b96843 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/jobs/IndividualSendJobV2Test.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/jobs/IndividualSendJobV2Test.kt @@ -10,6 +10,7 @@ import androidx.test.core.app.ApplicationProvider import arrow.core.left import arrow.core.right import assertk.assertThat +import assertk.assertions.isEqualTo import assertk.assertions.isTrue import io.mockk.coEvery import io.mockk.coVerify @@ -19,6 +20,7 @@ import io.mockk.mockk import io.mockk.mockkObject import io.mockk.mockkStatic import io.mockk.runs +import io.mockk.slot import io.mockk.unmockkAll import io.mockk.verify import org.junit.After @@ -425,6 +427,45 @@ class IndividualSendJobV2Test { } } + @Test + fun `Given an edit of an already-edited message, when run, then target the edited revision's dateSent`() { + val editTargetMessageId = messageId + 1 + val editRevisionSentTime = sentTime + 10_000L + // An edit revision inherits the original message's dateReceived, so getTimestamp() returns a value + // that is not the revision's actual sent timestamp. The edit target must use dateSent. + val inheritedTimestamp = sentTime - 2L + + every { outgoingMessage.messageToEdit } returns editTargetMessageId + + val editTargetRecord: MessageRecord = mockk(relaxed = true) + every { editTargetRecord.dateSent } returns editRevisionSentTime + every { editTargetRecord.timestamp } returns inheritedTimestamp + every { editTargetRecord.expireStarted } returns 0L + every { messages.getMessageRecordOrNull(editTargetMessageId) } returns editTargetRecord + + val contentSlot = slot() + coEvery { + messageService.sendMessage( + serviceId = any(), + envelopeContent = capture(contentSlot), + timestamp = any(), + sealedSenderAccess = any(), + story = any(), + isOnline = any(), + urgent = any(), + onEncrypted = any() + ) + } returns MessageService.SendSuccess( + envelopeContent = EnvelopeContent.encrypted(Content(dataMessage = dataMessage), ContentHint.RESENDABLE, Optional.empty()), + sentSealedSender = false, + devices = listOf(1) + ).right() + + createAndRunJob() + + assertThat(contentSlot.captured.content.get().editMessage!!.targetSentTimestamp).isEqualTo(editRevisionSentTime) + } + @Test fun `Given a send needs PNI signature, when send succeeds, then write a pending PNI signature record`() { every { recipient.needsPniSignature } returns true