From ccfbfeffe22697c33d5f1e2f5906551a13ee9505 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Wed, 7 Jun 2023 12:25:11 -0400 Subject: [PATCH] Moves ChatroomList's New Feed to an Additive filter. --- .../ui/dal/ChatroomListNewFeedFilter.kt | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListNewFeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListNewFeedFilter.kt index ec361e012..cad55b4a2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListNewFeedFilter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/ChatroomListNewFeedFilter.kt @@ -1,9 +1,14 @@ package com.vitorpamplona.amethyst.ui.dal import com.vitorpamplona.amethyst.model.Account +import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.service.model.PrivateDmEvent +import com.vitorpamplona.amethyst.ui.actions.updated +import kotlin.time.ExperimentalTime +import kotlin.time.measureTimedValue -class ChatroomListNewFeedFilter(val account: Account) : FeedFilter() { +class ChatroomListNewFeedFilter(val account: Account) : AdditiveFeedFilter() { // returns the last Note of each user. override fun feed(): List { @@ -26,4 +31,80 @@ class ChatroomListNewFeedFilter(val account: Account) : FeedFilter() { .sortedWith(compareBy({ it.createdAt() }, { it.idHex })) .reversed() } + + @OptIn(ExperimentalTime::class) + override fun updateListWith(oldList: List, newItems: Set): List { + val (feed, elapsed) = measureTimedValue { + val me = account.userProfile() + + // Gets the latest message by room from the new items. + val newRelevantPrivateMessages = filterRelevantPrivateMessages(newItems, account) + + if (newRelevantPrivateMessages.isEmpty()) { + return oldList + } + + var myNewList = oldList + + newRelevantPrivateMessages.forEach { newNotePair -> + oldList.forEach { oldNote -> + val oldRoom = (oldNote.event as? PrivateDmEvent)?.talkingWith(me.pubkeyHex) + + if ( + (newNotePair.key == oldRoom) && (newNotePair.value.createdAt() ?: 0) > (oldNote.createdAt() ?: 0) + ) { + myNewList = myNewList.updated(oldNote, newNotePair.value) + } + } + } + + sort(myNewList.toSet()).take(1000) + } + + // Log.d("Time", "${this.javaClass.simpleName} Modified Additive Feed in $elapsed with ${feed.size} objects") + return feed + } + + override fun applyFilter(newItems: Set): Set { + // Gets the latest message by room from the new items. + val newRelevantPrivateMessages = filterRelevantPrivateMessages(newItems, account) + + return if (newRelevantPrivateMessages.isEmpty()) { + emptySet() + } else { + newRelevantPrivateMessages.values.toSet() + } + } + + private fun filterRelevantPrivateMessages(newItems: Set, account: Account): MutableMap { + val me = account.userProfile() + val followingKeySet = account.followingKeySet() + + val newRelevantPrivateMessages = mutableMapOf() + newItems.filter { it.event is PrivateDmEvent }.forEach { newNote -> + val roomUserHex = (newNote.event as? PrivateDmEvent)?.talkingWith(me.pubkeyHex) + val roomUser = roomUserHex?.let { LocalCache.users[it] } + + if (roomUserHex != null && + (newNote.author?.pubkeyHex != me.pubkeyHex && roomUserHex !in followingKeySet && !me.hasSentMessagesTo(roomUser)) && + !account.isHidden(roomUserHex) + ) { + val lastNote = newRelevantPrivateMessages.get(roomUserHex) + if (lastNote != null) { + if ((newNote.createdAt() ?: 0) > (lastNote.createdAt() ?: 0)) { + newRelevantPrivateMessages.put(roomUserHex, newNote) + } + } else { + newRelevantPrivateMessages.put(roomUserHex, newNote) + } + } + } + return newRelevantPrivateMessages + } + + override fun sort(collection: Set): List { + return collection + .sortedWith(compareBy({ it.createdAt() }, { it.idHex })) + .reversed() + } }