mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-26 12:44:38 +00:00
Add process read sync tests.
This commit is contained in:
@@ -52,7 +52,7 @@ class MessageContentProcessor__recipientStatusTest {
|
||||
processor.process(
|
||||
envelope = MessageContentFuzzer.envelope(envelopeTimestamp),
|
||||
content = MessageContentFuzzer.syncSentTextMessage(initialTextMessage, deliveredTo = listOf(harness.others[0])),
|
||||
metadata = MessageContentFuzzer.envelopeMetadata(harness.self.id, harness.self.id, groupId),
|
||||
metadata = MessageContentFuzzer.envelopeMetadata(harness.self.id, harness.self.id, groupId = groupId),
|
||||
serverDeliveredTimestamp = MessageContentFuzzer.fuzzServerDeliveredTimestamp(envelopeTimestamp)
|
||||
)
|
||||
|
||||
@@ -64,7 +64,7 @@ class MessageContentProcessor__recipientStatusTest {
|
||||
processor.process(
|
||||
envelope = MessageContentFuzzer.envelope(envelopeTimestamp),
|
||||
content = MessageContentFuzzer.syncSentTextMessage(initialTextMessage, deliveredTo = listOf(harness.others[0], harness.others[1]), recipientUpdate = true),
|
||||
metadata = MessageContentFuzzer.envelopeMetadata(harness.self.id, harness.self.id, groupId),
|
||||
metadata = MessageContentFuzzer.envelopeMetadata(harness.self.id, harness.self.id, groupId = groupId),
|
||||
serverDeliveredTimestamp = MessageContentFuzzer.fuzzServerDeliveredTimestamp(envelopeTimestamp)
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.messages
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import io.mockk.every
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.slot
|
||||
import io.mockk.unmockkStatic
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.jobs.ThreadUpdateJob
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.testing.GroupTestingUtils
|
||||
import org.thoughtcrime.securesms.testing.MessageContentFuzzer
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
import org.thoughtcrime.securesms.testing.assertIs
|
||||
import java.util.UUID
|
||||
|
||||
@Suppress("ClassName")
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class SyncMessageProcessorTest_readSyncs {
|
||||
|
||||
@get:Rule
|
||||
val harness = SignalActivityRule(createGroup = true)
|
||||
|
||||
private lateinit var alice: RecipientId
|
||||
private lateinit var bob: RecipientId
|
||||
private lateinit var group: GroupTestingUtils.TestGroupInfo
|
||||
private lateinit var processor: MessageContentProcessor
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
alice = harness.others[0]
|
||||
bob = harness.others[1]
|
||||
group = harness.group!!
|
||||
|
||||
processor = MessageContentProcessor(harness.context)
|
||||
|
||||
val threadIdSlot = slot<Long>()
|
||||
mockkStatic(ThreadUpdateJob::class)
|
||||
every { ThreadUpdateJob.enqueue(capture(threadIdSlot)) } answers {
|
||||
SignalDatabase.threads.update(threadIdSlot.captured, false)
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkStatic(ThreadUpdateJob::class)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleSynchronizeReadMessage() {
|
||||
val messageHelper = MessageHelper()
|
||||
|
||||
val message1Timestamp = messageHelper.incomingText().timestamp
|
||||
val message2Timestamp = messageHelper.incomingText().timestamp
|
||||
|
||||
val threadId = SignalDatabase.threads.getThreadIdFor(alice)!!
|
||||
var threadRecord = SignalDatabase.threads.getThreadRecord(threadId)!!
|
||||
threadRecord.unreadCount assertIs 2
|
||||
|
||||
messageHelper.syncReadMessage(alice to message1Timestamp, alice to message2Timestamp)
|
||||
|
||||
threadRecord = SignalDatabase.threads.getThreadRecord(threadId)!!
|
||||
threadRecord.unreadCount assertIs 0
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleSynchronizeReadMessageMissingTimestamp() {
|
||||
val messageHelper = MessageHelper()
|
||||
|
||||
messageHelper.incomingText().timestamp
|
||||
val message2Timestamp = messageHelper.incomingText().timestamp
|
||||
|
||||
val threadId = SignalDatabase.threads.getThreadIdFor(alice)!!
|
||||
var threadRecord = SignalDatabase.threads.getThreadRecord(threadId)!!
|
||||
threadRecord.unreadCount assertIs 2
|
||||
|
||||
messageHelper.syncReadMessage(alice to message2Timestamp)
|
||||
|
||||
threadRecord = SignalDatabase.threads.getThreadRecord(threadId)!!
|
||||
threadRecord.unreadCount assertIs 0
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleSynchronizeReadWithEdits() {
|
||||
val messageHelper = MessageHelper()
|
||||
|
||||
val message1Timestamp = messageHelper.incomingText().timestamp
|
||||
messageHelper.syncReadMessage(alice to message1Timestamp)
|
||||
|
||||
val editMessage1Timestamp1 = messageHelper.incomingEditText(message1Timestamp).timestamp
|
||||
val editMessage1Timestamp2 = messageHelper.incomingEditText(editMessage1Timestamp1).timestamp
|
||||
|
||||
val message2Timestamp = messageHelper.incomingMedia().timestamp
|
||||
|
||||
val threadId = SignalDatabase.threads.getThreadIdFor(alice)!!
|
||||
var threadRecord = SignalDatabase.threads.getThreadRecord(threadId)!!
|
||||
threadRecord.unreadCount assertIs 2
|
||||
|
||||
messageHelper.syncReadMessage(alice to message2Timestamp, alice to editMessage1Timestamp1, alice to editMessage1Timestamp2)
|
||||
|
||||
threadRecord = SignalDatabase.threads.getThreadRecord(threadId)!!
|
||||
threadRecord.unreadCount assertIs 0
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleSynchronizeReadWithEditsInGroup() {
|
||||
val messageHelper = MessageHelper()
|
||||
|
||||
val message1Timestamp = messageHelper.incomingText(sender = alice, destination = group.recipientId).timestamp
|
||||
|
||||
messageHelper.syncReadMessage(alice to message1Timestamp)
|
||||
|
||||
val editMessage1Timestamp1 = messageHelper.incomingEditText(targetTimestamp = message1Timestamp, sender = alice, destination = group.recipientId).timestamp
|
||||
val editMessage1Timestamp2 = messageHelper.incomingEditText(targetTimestamp = editMessage1Timestamp1, sender = alice, destination = group.recipientId).timestamp
|
||||
|
||||
val message2Timestamp = messageHelper.incomingMedia(sender = bob, destination = group.recipientId).timestamp
|
||||
|
||||
val threadId = SignalDatabase.threads.getThreadIdFor(group.recipientId)!!
|
||||
var threadRecord = SignalDatabase.threads.getThreadRecord(threadId)!!
|
||||
threadRecord.unreadCount assertIs 2
|
||||
|
||||
messageHelper.syncReadMessage(bob to message2Timestamp, alice to editMessage1Timestamp1, alice to editMessage1Timestamp2)
|
||||
|
||||
threadRecord = SignalDatabase.threads.getThreadRecord(threadId)!!
|
||||
threadRecord.unreadCount assertIs 0
|
||||
}
|
||||
|
||||
private inner class MessageHelper(var startTime: Long = System.currentTimeMillis()) {
|
||||
|
||||
fun incomingText(sender: RecipientId = alice, destination: RecipientId = harness.self.id): MessageData {
|
||||
startTime += 1000
|
||||
|
||||
val messageData = MessageData(timestamp = startTime)
|
||||
|
||||
processor.process(
|
||||
envelope = MessageContentFuzzer.envelope(messageData.timestamp, serverGuid = messageData.serverGuid),
|
||||
content = MessageContentFuzzer.fuzzTextMessage(
|
||||
sentTimestamp = messageData.timestamp,
|
||||
groupContextV2 = if (destination == group.recipientId) group.groupV2Context else null
|
||||
),
|
||||
metadata = MessageContentFuzzer.envelopeMetadata(
|
||||
source = sender,
|
||||
destination = harness.self.id,
|
||||
groupId = if (destination == group.recipientId) group.groupId else null
|
||||
),
|
||||
serverDeliveredTimestamp = messageData.timestamp + 10
|
||||
)
|
||||
|
||||
return messageData
|
||||
}
|
||||
|
||||
fun incomingMedia(sender: RecipientId = alice, destination: RecipientId = harness.self.id): MessageData {
|
||||
startTime += 1000
|
||||
|
||||
val messageData = MessageData(timestamp = startTime)
|
||||
|
||||
processor.process(
|
||||
envelope = MessageContentFuzzer.envelope(messageData.timestamp, serverGuid = messageData.serverGuid),
|
||||
content = MessageContentFuzzer.fuzzStickerMediaMessage(
|
||||
sentTimestamp = messageData.timestamp,
|
||||
groupContextV2 = if (destination == group.recipientId) group.groupV2Context else null
|
||||
),
|
||||
metadata = MessageContentFuzzer.envelopeMetadata(
|
||||
source = sender,
|
||||
destination = harness.self.id,
|
||||
groupId = if (destination == group.recipientId) group.groupId else null
|
||||
),
|
||||
serverDeliveredTimestamp = messageData.timestamp + 10
|
||||
)
|
||||
|
||||
return messageData
|
||||
}
|
||||
|
||||
fun incomingEditText(targetTimestamp: Long = System.currentTimeMillis(), sender: RecipientId = alice, destination: RecipientId = harness.self.id): MessageData {
|
||||
startTime += 1000
|
||||
|
||||
val messageData = MessageData(timestamp = startTime)
|
||||
|
||||
processor.process(
|
||||
envelope = MessageContentFuzzer.envelope(messageData.timestamp, serverGuid = messageData.serverGuid),
|
||||
content = MessageContentFuzzer.editTextMessage(
|
||||
targetTimestamp = targetTimestamp,
|
||||
editedDataMessage = MessageContentFuzzer.fuzzTextMessage(
|
||||
sentTimestamp = messageData.timestamp,
|
||||
groupContextV2 = if (destination == group.recipientId) group.groupV2Context else null
|
||||
).dataMessage!!
|
||||
),
|
||||
metadata = MessageContentFuzzer.envelopeMetadata(
|
||||
source = sender,
|
||||
destination = harness.self.id,
|
||||
groupId = if (destination == group.recipientId) group.groupId else null
|
||||
),
|
||||
serverDeliveredTimestamp = messageData.timestamp + 10
|
||||
)
|
||||
|
||||
return messageData
|
||||
}
|
||||
|
||||
fun syncReadMessage(vararg reads: Pair<RecipientId, Long>): MessageData {
|
||||
startTime += 1000
|
||||
val messageData = MessageData(timestamp = startTime)
|
||||
|
||||
processor.process(
|
||||
envelope = MessageContentFuzzer.envelope(messageData.timestamp, serverGuid = messageData.serverGuid),
|
||||
content = MessageContentFuzzer.syncReadsMessage(reads.toList()),
|
||||
metadata = MessageContentFuzzer.envelopeMetadata(harness.self.id, harness.self.id, sourceDeviceId = 2),
|
||||
serverDeliveredTimestamp = messageData.timestamp + 10
|
||||
)
|
||||
|
||||
return messageData
|
||||
}
|
||||
}
|
||||
|
||||
private data class MessageData(val serverGuid: UUID = UUID.randomUUID(), val timestamp: Long)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.thoughtcrime.securesms.testing
|
||||
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey
|
||||
import org.signal.storageservice.protos.groups.Member
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup
|
||||
@@ -9,6 +10,7 @@ import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.internal.push.GroupContextV2
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
@@ -46,5 +48,8 @@ object GroupTestingUtils {
|
||||
return member(aci = requireAci())
|
||||
}
|
||||
|
||||
data class TestGroupInfo(val groupId: GroupId.V2, val masterKey: GroupMasterKey, val recipientId: RecipientId)
|
||||
data class TestGroupInfo(val groupId: GroupId.V2, val masterKey: GroupMasterKey, val recipientId: RecipientId) {
|
||||
val groupV2Context: GroupContextV2
|
||||
get() = GroupContextV2(masterKey = masterKey.serialize().toByteString(), revision = 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.whispersystems.signalservice.internal.push.AttachmentPointer
|
||||
import org.whispersystems.signalservice.internal.push.BodyRange
|
||||
import org.whispersystems.signalservice.internal.push.Content
|
||||
import org.whispersystems.signalservice.internal.push.DataMessage
|
||||
import org.whispersystems.signalservice.internal.push.EditMessage
|
||||
import org.whispersystems.signalservice.internal.push.Envelope
|
||||
import org.whispersystems.signalservice.internal.push.GroupContextV2
|
||||
import org.whispersystems.signalservice.internal.push.SyncMessage
|
||||
@@ -33,22 +34,22 @@ object MessageContentFuzzer {
|
||||
/**
|
||||
* Create an [Envelope].
|
||||
*/
|
||||
fun envelope(timestamp: Long): Envelope {
|
||||
fun envelope(timestamp: Long, serverGuid: UUID = UUID.randomUUID()): Envelope {
|
||||
return Envelope.Builder()
|
||||
.timestamp(timestamp)
|
||||
.serverTimestamp(timestamp + 5)
|
||||
.serverGuid(UUID.randomUUID().toString())
|
||||
.serverGuid(serverGuid.toString())
|
||||
.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create metadata to match an [Envelope].
|
||||
*/
|
||||
fun envelopeMetadata(source: RecipientId, destination: RecipientId, groupId: GroupId.V2? = null): EnvelopeMetadata {
|
||||
fun envelopeMetadata(source: RecipientId, destination: RecipientId, sourceDeviceId: Int = 1, groupId: GroupId.V2? = null): EnvelopeMetadata {
|
||||
return EnvelopeMetadata(
|
||||
sourceServiceId = Recipient.resolved(source).requireServiceId(),
|
||||
sourceE164 = null,
|
||||
sourceDeviceId = 1,
|
||||
sourceDeviceId = sourceDeviceId,
|
||||
sealedSender = true,
|
||||
groupId = groupId?.decodedId,
|
||||
destinationServiceId = Recipient.resolved(destination).requireServiceId()
|
||||
@@ -60,10 +61,11 @@ object MessageContentFuzzer {
|
||||
* - An expire timer value
|
||||
* - Bold style body ranges
|
||||
*/
|
||||
fun fuzzTextMessage(groupContextV2: GroupContextV2? = null): Content {
|
||||
fun fuzzTextMessage(sentTimestamp: Long? = null, groupContextV2: GroupContextV2? = null): Content {
|
||||
return Content.Builder()
|
||||
.dataMessage(
|
||||
DataMessage.Builder().buildWith {
|
||||
timestamp = sentTimestamp
|
||||
body = string()
|
||||
if (random.nextBoolean()) {
|
||||
expireTimer = random.nextInt(0..28.days.inWholeSeconds.toInt())
|
||||
@@ -87,6 +89,20 @@ object MessageContentFuzzer {
|
||||
.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an edit message.
|
||||
*/
|
||||
fun editTextMessage(targetTimestamp: Long, editedDataMessage: DataMessage): Content {
|
||||
return Content.Builder()
|
||||
.editMessage(
|
||||
EditMessage.Builder().buildWith {
|
||||
targetSentTimestamp = targetTimestamp
|
||||
dataMessage = editedDataMessage
|
||||
}
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sync sent text message for the given [DataMessage].
|
||||
*/
|
||||
@@ -116,6 +132,24 @@ object MessageContentFuzzer {
|
||||
).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sync reads message for the given [RecipientId] and message timestamp pairings.
|
||||
*/
|
||||
fun syncReadsMessage(timestamps: List<Pair<RecipientId, Long>>): Content {
|
||||
return Content
|
||||
.Builder()
|
||||
.syncMessage(
|
||||
SyncMessage.Builder().buildWith {
|
||||
read = timestamps.map { (senderId, timestamp) ->
|
||||
SyncMessage.Read.Builder().buildWith {
|
||||
this.senderAci = Recipient.resolved(senderId).requireAci().toString()
|
||||
this.timestamp = timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a random media message that may be:
|
||||
* - A text body
|
||||
@@ -184,22 +218,21 @@ object MessageContentFuzzer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a random media message that can never contain a text body. It may be:
|
||||
* - A sticker
|
||||
* Create a random media message that contains a sticker.
|
||||
*/
|
||||
fun fuzzMediaMessageNoText(previousMessages: List<TestMessage> = emptyList()): Content {
|
||||
fun fuzzStickerMediaMessage(sentTimestamp: Long? = null, groupContextV2: GroupContextV2? = null): Content {
|
||||
return Content.Builder()
|
||||
.dataMessage(
|
||||
DataMessage.Builder().buildWith {
|
||||
if (random.nextFloat() < 0.9) {
|
||||
sticker = DataMessage.Sticker.Builder().buildWith {
|
||||
packId = byteString(length = 24)
|
||||
packKey = byteString(length = 128)
|
||||
stickerId = random.nextInt()
|
||||
data_ = attachmentPointer()
|
||||
emoji = emojis.random(random)
|
||||
}
|
||||
timestamp = sentTimestamp
|
||||
sticker = DataMessage.Sticker.Builder().buildWith {
|
||||
packId = byteString(length = 24)
|
||||
packKey = byteString(length = 128)
|
||||
stickerId = random.nextInt()
|
||||
data_ = attachmentPointer()
|
||||
emoji = emojis.random(random)
|
||||
}
|
||||
groupV2 = groupContextV2
|
||||
}
|
||||
).build()
|
||||
}
|
||||
|
||||
@@ -136,7 +136,6 @@ import org.thoughtcrime.securesms.util.MessageConstraintsUtil
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.thoughtcrime.securesms.util.isStory
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.internal.push.SyncMessage
|
||||
import java.io.Closeable
|
||||
@@ -4379,17 +4378,17 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
/**
|
||||
* @return Unhandled ids
|
||||
*/
|
||||
fun setTimestampReadFromSyncMessage(readMessages: List<ReadMessage>, proposedExpireStarted: Long, threadToLatestRead: MutableMap<Long, Long>): Collection<SyncMessageId> {
|
||||
fun setTimestampReadFromSyncMessage(readMessages: List<SyncMessage.Read>, proposedExpireStarted: Long, threadToLatestRead: MutableMap<Long, Long>): Collection<SyncMessageId> {
|
||||
val expiringMessages: MutableList<Pair<Long, Long>> = mutableListOf()
|
||||
val updatedThreads: MutableSet<Long> = mutableSetOf()
|
||||
val unhandled: MutableCollection<SyncMessageId> = mutableListOf()
|
||||
|
||||
writableDatabase.withinTransaction {
|
||||
for (readMessage in readMessages) {
|
||||
val authorId: RecipientId = recipients.getOrInsertFromServiceId(readMessage.sender)
|
||||
val authorId: RecipientId = recipients.getOrInsertFromServiceId(ServiceId.parseOrThrow(readMessage.senderAci!!))
|
||||
|
||||
val result: TimestampReadResult = setTimestampReadFromSyncMessageInternal(
|
||||
messageId = SyncMessageId(authorId, readMessage.timestamp),
|
||||
messageId = SyncMessageId(authorId, readMessage.timestamp!!),
|
||||
proposedExpireStarted = proposedExpireStarted,
|
||||
threadToLatestRead = threadToLatestRead
|
||||
)
|
||||
@@ -4398,7 +4397,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
updatedThreads += result.threads
|
||||
|
||||
if (result.threads.isEmpty()) {
|
||||
unhandled += SyncMessageId(authorId, readMessage.timestamp)
|
||||
unhandled += SyncMessageId(authorId, readMessage.timestamp!!)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4419,12 +4418,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
return unhandled
|
||||
}
|
||||
|
||||
fun setTimestampReadFromSyncMessageProto(readMessages: List<SyncMessage.Read>, proposedExpireStarted: Long, threadToLatestRead: MutableMap<Long, Long>): Collection<SyncMessageId> {
|
||||
val reads: List<ReadMessage> = readMessages.map { r -> ReadMessage(ServiceId.parseOrThrow(r.senderAci!!), r.timestamp!!) }
|
||||
|
||||
return setTimestampReadFromSyncMessage(reads, proposedExpireStarted, threadToLatestRead)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a synchronized read message.
|
||||
* @param messageId An id representing the author-timestamp pair of the message that was read on a linked device. Note that the author could be self when
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.database.CallLinkTable
|
||||
import org.thoughtcrime.securesms.database.CallTable
|
||||
import org.thoughtcrime.securesms.database.GroupReceiptTable
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
import org.thoughtcrime.securesms.database.MessageTable
|
||||
import org.thoughtcrime.securesms.database.MessageTable.MarkedMessageInfo
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException
|
||||
import org.thoughtcrime.securesms.database.PaymentMetaDataUtil
|
||||
@@ -916,9 +917,9 @@ object SyncMessageProcessor {
|
||||
) {
|
||||
log(envelopeTimestamp, "Synchronize read message. Count: ${readMessages.size}, Timestamps: ${readMessages.map { it.timestamp }}")
|
||||
|
||||
val threadToLatestRead: Map<Long, Long> = HashMap()
|
||||
val unhandled = SignalDatabase.messages.setTimestampReadFromSyncMessageProto(readMessages, envelopeTimestamp, threadToLatestRead.toMutableMap())
|
||||
val markedMessages: List<MarkedMessageInfo?> = SignalDatabase.threads.setReadSince(threadToLatestRead, false)
|
||||
val threadToLatestRead: MutableMap<Long, Long> = HashMap()
|
||||
val unhandled: Collection<MessageTable.SyncMessageId> = SignalDatabase.messages.setTimestampReadFromSyncMessage(readMessages, envelopeTimestamp, threadToLatestRead)
|
||||
val markedMessages: List<MarkedMessageInfo> = SignalDatabase.threads.setReadSince(threadToLatestRead, false)
|
||||
|
||||
if (Util.hasItems(markedMessages)) {
|
||||
log("Updating past SignalDatabase.messages: " + markedMessages.size)
|
||||
|
||||
Reference in New Issue
Block a user