Update last seen logic to used last read message instead of now timestamp.

This commit is contained in:
Cody Henthorne
2025-02-11 16:13:55 -05:00
committed by Greyson Parrelli
parent d7221a384b
commit b82d16abcb
15 changed files with 83 additions and 69 deletions

View File

@@ -734,7 +734,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun getViewedIncomingMessages(threadId: Long): List<MarkedMessageInfo> {
return readableDatabase
.select(ID, FROM_RECIPIENT_ID, DATE_SENT, TYPE, THREAD_ID, STORY_TYPE)
.select(ID, FROM_RECIPIENT_ID, DATE_RECEIVED, DATE_SENT, TYPE, THREAD_ID, STORY_TYPE)
.from(TABLE_NAME)
.where("$THREAD_ID = ? AND $VIEWED_COLUMN > 0 AND $TYPE & ${MessageTypes.BASE_INBOX_TYPE} = ${MessageTypes.BASE_INBOX_TYPE}", threadId)
.run()
@@ -756,7 +756,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
}
val results: List<MarkedMessageInfo> = readableDatabase
.select(ID, FROM_RECIPIENT_ID, DATE_SENT, TYPE, THREAD_ID, STORY_TYPE)
.select(ID, FROM_RECIPIENT_ID, DATE_SENT, DATE_RECEIVED, TYPE, THREAD_ID, STORY_TYPE)
.from(TABLE_NAME)
.where("$ID IN (${Util.join(messageIds, ",")}) AND $VIEWED_COLUMN = 0")
.run()
@@ -803,7 +803,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun setOutgoingGiftsRevealed(messageIds: List<Long>): List<MarkedMessageInfo> {
val results: List<MarkedMessageInfo> = readableDatabase
.select(ID, TO_RECIPIENT_ID, DATE_SENT, THREAD_ID, STORY_TYPE)
.select(ID, TO_RECIPIENT_ID, DATE_SENT, DATE_RECEIVED, THREAD_ID, STORY_TYPE)
.from(TABLE_NAME)
.where("""$ID IN (${Util.join(messageIds, ",")}) AND ($outgoingTypeClause) AND ($TYPE & ${MessageTypes.SPECIAL_TYPES_MASK} = ${MessageTypes.SPECIAL_TYPE_GIFT_BADGE}) AND $VIEWED_COLUMN = 0""")
.run()
@@ -2346,13 +2346,14 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
UPDATE $TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID
SET $READ = 1, $REACTIONS_UNREAD = 0, $REACTIONS_LAST_SEEN = ${System.currentTimeMillis()}
WHERE $where
RETURNING $ID, $FROM_RECIPIENT_ID, $DATE_SENT, $TYPE, $EXPIRES_IN, $EXPIRE_STARTED, $THREAD_ID, $STORY_TYPE
RETURNING $ID, $FROM_RECIPIENT_ID, $DATE_SENT, $DATE_RECEIVED, $TYPE, $EXPIRES_IN, $EXPIRE_STARTED, $THREAD_ID, $STORY_TYPE
""",
arguments ?: emptyArray()
).readToList { cursor ->
val threadId = cursor.requireLong(THREAD_ID)
val recipientId = RecipientId.from(cursor.requireLong(FROM_RECIPIENT_ID))
val dateSent = cursor.requireLong(DATE_SENT)
val dateReceived = cursor.requireLong(DATE_RECEIVED)
val messageId = cursor.requireLong(ID)
val expiresIn = cursor.requireLong(EXPIRES_IN)
val expireStarted = cursor.requireLong(EXPIRE_STARTED)
@@ -2361,7 +2362,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
val storyType = fromCode(CursorUtil.requireInt(cursor, STORY_TYPE))
if (recipientId != releaseChannelId) {
MarkedMessageInfo(threadId, syncMessageId, MessageId(messageId), expirationInfo, storyType)
MarkedMessageInfo(threadId, syncMessageId, MessageId(messageId), expirationInfo, storyType, dateReceived)
} else {
null
}
@@ -3005,12 +3006,14 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
}
}
val dateReceived = editedMessage?.dateReceived ?: System.currentTimeMillis()
val contentValues = ContentValues()
contentValues.put(DATE_SENT, message.sentTimeMillis)
contentValues.put(TYPE, type)
contentValues.put(THREAD_ID, threadId)
contentValues.put(READ, 1)
contentValues.put(DATE_RECEIVED, editedMessage?.dateReceived ?: System.currentTimeMillis())
contentValues.put(DATE_RECEIVED, dateReceived)
contentValues.put(SMS_SUBSCRIPTION_ID, message.subscriptionId)
contentValues.put(EXPIRES_IN, editedMessage?.expiresIn ?: message.expiresIn)
contentValues.put(EXPIRE_TIMER_VERSION, editedMessage?.expireTimerVersion ?: message.expireTimerVersion)
@@ -3136,7 +3139,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
reactions.moveReactionsToNewMessage(messageId, message.messageToEdit)
}
threads.updateLastSeenAndMarkSentAndLastScrolledSilenty(threadId)
threads.updateLastSeenAndMarkSentAndLastScrolledSilenty(threadId, dateReceived)
if (!message.storyType.isStory) {
if (message.outgoingQuote == null && editedMessage == null) {
@@ -4209,11 +4212,11 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
.take(limit.toInt())
}
fun getMessagePositionOnOrAfterTimestamp(threadId: Long, timestamp: Long): Int {
fun getMessagePositionByDateReceivedTimestamp(threadId: Long, timestamp: Long, inclusive: Boolean): Int {
return readableDatabase
.select("COUNT(*)")
.from(TABLE_NAME)
.where("$THREAD_ID = $threadId AND $DATE_RECEIVED >= $timestamp AND $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $SCHEDULED_DATE = -1 AND $LATEST_REVISION_ID IS NULL")
.where("$THREAD_ID = $threadId AND $DATE_RECEIVED ${if (inclusive) ">=" else ">"} $timestamp AND $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $SCHEDULED_DATE = -1 AND $LATEST_REVISION_ID IS NULL")
.run()
.readToSingleInt()
}
@@ -4593,7 +4596,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
for (threadId in updatedThreads) {
threads.updateReadState(threadId)
threads.setLastSeen(threadId)
}
}
@@ -5004,7 +5006,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
timetamp = this.requireLong(DATE_SENT)
),
expirationInfo = null,
storyType = StoryType.fromCode(this.requireInt(STORY_TYPE))
storyType = StoryType.fromCode(this.requireInt(STORY_TYPE)),
dateReceived = this.requireLong(DATE_RECEIVED)
)
}
@@ -5072,6 +5075,17 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
return !hasMessages
}
fun getMostRecentReadMessageDateReceived(threadId: Long): Long? {
return readableDatabase
.select(DATE_RECEIVED)
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID")
.where("$THREAD_ID = ? AND $READ = 1", threadId)
.orderBy("$DATE_RECEIVED DESC")
.limit(1)
.run()
.readToSingleLongOrNull()
}
fun getMostRecentAddressableMessages(threadId: Long, excludeExpiring: Boolean): Set<MessageRecord> {
return readableDatabase
.select(*MMS_PROJECTION)
@@ -5144,7 +5158,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
val syncMessageId: SyncMessageId,
val messageId: MessageId,
val expirationInfo: ExpirationInfo?,
val storyType: StoryType
val storyType: StoryType,
val dateReceived: Long
)
data class InsertResult(

View File

@@ -471,6 +471,23 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
.run()
val messageRecords: List<MarkedMessageInfo> = messages.setAllMessagesRead()
val threadsToMessages = messageRecords.groupBy { it.threadId }
writableDatabase.withinTransaction {
threadsToMessages.forEach { (threadId, messages) ->
val latestDateReceived = messages.maxByOrNull { it.dateReceived }?.dateReceived
if (latestDateReceived != null && latestDateReceived > 0) {
writableDatabase
.update(TABLE_NAME)
.values(
LAST_SCROLLED to 0,
LAST_SEEN to latestDateReceived
)
.where(ID_WHERE, threadId)
.run()
}
}
}
messages.setAllReactionsSeen()
notifyConversationListListeners()
@@ -487,43 +504,43 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
}
fun setEntireThreadRead(threadId: Long): List<MarkedMessageInfo> {
setRead(threadId, false)
setRead(threadId)
return messages.setEntireThreadRead(threadId)
}
fun setRead(threadId: Long, lastSeen: Boolean): List<MarkedMessageInfo> {
return setReadSince(Collections.singletonMap(threadId, -1L), lastSeen)
fun setRead(threadId: Long): List<MarkedMessageInfo> {
return setReadSince(Collections.singletonMap(threadId, -1L))
}
fun setRead(conversationId: ConversationId, lastSeen: Boolean): List<MarkedMessageInfo> {
fun setRead(conversationId: ConversationId): List<MarkedMessageInfo> {
return if (conversationId.groupStoryId == null) {
setRead(conversationId.threadId, lastSeen)
setRead(conversationId.threadId)
} else {
setGroupStoryReadSince(conversationId.threadId, conversationId.groupStoryId, System.currentTimeMillis())
}
}
fun setReadSince(conversationId: ConversationId, lastSeen: Boolean, sinceTimestamp: Long): List<MarkedMessageInfo> {
fun setReadSince(conversationId: ConversationId, sinceTimestamp: Long): List<MarkedMessageInfo> {
return if (conversationId.groupStoryId != null) {
setGroupStoryReadSince(conversationId.threadId, conversationId.groupStoryId, sinceTimestamp)
} else {
setReadSince(conversationId.threadId, lastSeen, sinceTimestamp)
setReadSince(conversationId.threadId, sinceTimestamp)
}
}
fun setReadSince(threadId: Long, lastSeen: Boolean, sinceTimestamp: Long): List<MarkedMessageInfo> {
return setReadSince(Collections.singletonMap(threadId, sinceTimestamp), lastSeen)
fun setReadSince(threadId: Long, sinceTimestamp: Long): List<MarkedMessageInfo> {
return setReadSince(Collections.singletonMap(threadId, sinceTimestamp))
}
fun setRead(threadIds: Collection<Long>, lastSeen: Boolean): List<MarkedMessageInfo> {
return setReadSince(threadIds.associateWith { -1L }, lastSeen)
fun setRead(threadIds: Collection<Long>): List<MarkedMessageInfo> {
return setReadSince(threadIds.associateWith { -1L })
}
private fun setGroupStoryReadSince(threadId: Long, groupStoryId: Long, sinceTimestamp: Long): List<MarkedMessageInfo> {
return messages.setGroupStoryMessagesReadSince(threadId, groupStoryId, sinceTimestamp)
}
fun setReadSince(threadIdToSinceTimestamp: Map<Long, Long>, lastSeen: Boolean): List<MarkedMessageInfo> {
fun setReadSince(threadIdToSinceTimestamp: Map<Long, Long>): List<MarkedMessageInfo> {
val messageRecords: MutableList<MarkedMessageInfo> = LinkedList()
var needsSync = false
@@ -537,17 +554,15 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
val unreadCount = messages.getUnreadCount(threadId)
val unreadMentionsCount = messages.getUnreadMentionCount(threadId)
val lastSeenTimestamp = messages.getMostRecentReadMessageDateReceived(threadId) ?: System.currentTimeMillis()
val contentValues = contentValuesOf(
READ to ReadStatus.READ.serialize(),
UNREAD_COUNT to unreadCount,
UNREAD_SELF_MENTION_COUNT to unreadMentionsCount
UNREAD_SELF_MENTION_COUNT to unreadMentionsCount,
LAST_SEEN to lastSeenTimestamp
)
if (lastSeen) {
contentValues.put(LAST_SEEN, if (sinceTimestamp == -1L) System.currentTimeMillis() else sinceTimestamp)
}
db.update(TABLE_NAME)
.values(contentValues)
.where("$ID = ?", threadId)
@@ -1199,16 +1214,6 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
setArchived(setOf(threadId), archive = false)
}
fun setLastSeen(threadId: Long) {
writableDatabase
.update(TABLE_NAME)
.values(LAST_SEEN to System.currentTimeMillis())
.where("$ID = ?", threadId)
.run()
notifyConversationListListeners()
}
fun setLastScrolled(threadId: Long, lastScrolledTimestamp: Long) {
writableDatabase
.update(TABLE_NAME)
@@ -1488,14 +1493,19 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
.run()
}
fun updateLastSeenAndMarkSentAndLastScrolledSilenty(threadId: Long) {
fun updateLastSeenAndMarkSentAndLastScrolledSilenty(threadId: Long, lastSeenTimestamp: Long) {
val values = contentValuesOf(
HAS_SENT to 1,
LAST_SCROLLED to 0
)
if (lastSeenTimestamp > 0) {
values.put(LAST_SEEN, lastSeenTimestamp)
}
writableDatabase
.update(TABLE_NAME)
.values(
LAST_SEEN to System.currentTimeMillis(),
HAS_SENT to 1,
LAST_SCROLLED to 0
)
.values(values)
.where("$ID = ?", threadId)
.run()
}