Moving chatroomlist to an additive filter
This commit is contained in:
+124
-1
@@ -1,9 +1,16 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.dal
|
package com.vitorpamplona.amethyst.ui.dal
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import com.vitorpamplona.amethyst.model.Account
|
import com.vitorpamplona.amethyst.model.Account
|
||||||
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
||||||
|
import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.updated
|
||||||
|
import kotlin.time.ExperimentalTime
|
||||||
|
import kotlin.time.measureTimedValue
|
||||||
|
|
||||||
object ChatroomListKnownFeedFilter : FeedFilter<Note>() {
|
object ChatroomListKnownFeedFilter : AdditiveFeedFilter<Note>() {
|
||||||
lateinit var account: Account
|
lateinit var account: Account
|
||||||
|
|
||||||
// returns the last Note of each user.
|
// returns the last Note of each user.
|
||||||
@@ -35,4 +42,120 @@ object ChatroomListKnownFeedFilter : FeedFilter<Note>() {
|
|||||||
.sortedWith(compareBy({ it.createdAt() }, { it.idHex }))
|
.sortedWith(compareBy({ it.createdAt() }, { it.idHex }))
|
||||||
.reversed()
|
.reversed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalTime::class)
|
||||||
|
override fun updateListWith(oldList: List<Note>, newItems: Set<Note>): List<Note> {
|
||||||
|
val (feed, elapsed) = measureTimedValue {
|
||||||
|
val me = account.userProfile()
|
||||||
|
|
||||||
|
// Gets the latest message by channel from the new items.
|
||||||
|
val newRelevantPublicMessages = filterRelevantPublicMessages(newItems, account)
|
||||||
|
|
||||||
|
// Gets the latest message by room from the new items.
|
||||||
|
val newRelevantPrivateMessages = filterRelevantPrivateMessages(newItems, account)
|
||||||
|
|
||||||
|
if (newRelevantPrivateMessages.isEmpty() && newRelevantPublicMessages.isEmpty()) {
|
||||||
|
return oldList
|
||||||
|
}
|
||||||
|
|
||||||
|
var myNewList = oldList
|
||||||
|
|
||||||
|
newRelevantPublicMessages.forEach { newNotePair ->
|
||||||
|
oldList.forEach { oldNote ->
|
||||||
|
if (
|
||||||
|
(newNotePair.key == oldNote.channelHex()) && (newNotePair.value.createdAt() ?: 0) > (oldNote.createdAt() ?: 0)
|
||||||
|
) {
|
||||||
|
myNewList = myNewList.updated(oldNote, newNotePair.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newRelevantPrivateMessages.forEach { newNotePair ->
|
||||||
|
oldList.forEach { oldNote ->
|
||||||
|
val oldAuthor = oldNote.author?.pubkeyHex
|
||||||
|
val oldRecipient = (oldNote.event as? PrivateDmEvent)?.verifiedRecipientPubKey()
|
||||||
|
|
||||||
|
val oldRoom = if (oldAuthor == me.pubkeyHex) oldRecipient else oldAuthor
|
||||||
|
|
||||||
|
if (
|
||||||
|
(newNotePair.key == oldRoom) && (newNotePair.value.createdAt() ?: 0) > (oldNote.createdAt() ?: 0)
|
||||||
|
) {
|
||||||
|
myNewList = myNewList.updated(oldNote, newNotePair.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myNewList
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("Time", "${this.javaClass.simpleName} Modified Additive Feed in $elapsed with ${feed.size} objects")
|
||||||
|
return feed
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyFilter(newItems: Set<Note>): Set<Note> {
|
||||||
|
// Gets the latest message by channel from the new items.
|
||||||
|
val newRelevantPublicMessages = filterRelevantPublicMessages(newItems, account)
|
||||||
|
|
||||||
|
// Gets the latest message by room from the new items.
|
||||||
|
val newRelevantPrivateMessages = filterRelevantPrivateMessages(newItems, account)
|
||||||
|
|
||||||
|
return if (newRelevantPrivateMessages.isEmpty() && newRelevantPublicMessages.isEmpty()) {
|
||||||
|
emptySet()
|
||||||
|
} else {
|
||||||
|
(newRelevantPrivateMessages.values + newRelevantPublicMessages.values).toSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun filterRelevantPublicMessages(newItems: Set<Note>, account: Account): MutableMap<String, Note> {
|
||||||
|
val followingChannels = account.followingChannels
|
||||||
|
val newRelevantPublicMessages = mutableMapOf<String, Note>()
|
||||||
|
newItems.filter { it.event is ChannelMessageEvent }.forEach { newNote ->
|
||||||
|
newNote.channelHex()?.let { channelHex ->
|
||||||
|
if (channelHex in followingChannels && account.isAcceptable(newNote)) {
|
||||||
|
val lastNote = newRelevantPublicMessages.get(channelHex)
|
||||||
|
if (lastNote != null) {
|
||||||
|
if ((newNote.createdAt() ?: 0) > (lastNote.createdAt() ?: 0)) {
|
||||||
|
newRelevantPublicMessages.put(channelHex, newNote)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newRelevantPublicMessages.put(channelHex, newNote)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newRelevantPublicMessages
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun filterRelevantPrivateMessages(newItems: Set<Note>, account: Account): MutableMap<String, Note> {
|
||||||
|
val me = account.userProfile()
|
||||||
|
val followingKeySet = account.followingKeySet()
|
||||||
|
|
||||||
|
val newRelevantPrivateMessages = mutableMapOf<String, Note>()
|
||||||
|
newItems.filter { it.event is PrivateDmEvent }.forEach { newNote ->
|
||||||
|
val newAuthor = newNote.author?.pubkeyHex
|
||||||
|
val newRecipient = (newNote.event as? PrivateDmEvent)?.verifiedRecipientPubKey()
|
||||||
|
|
||||||
|
val roomUserHex = if (newAuthor == me.pubkeyHex) newRecipient else newAuthor
|
||||||
|
val roomUser = roomUserHex?.let { LocalCache.users[it] }
|
||||||
|
|
||||||
|
if (roomUserHex != null && (newAuthor == 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<Note>): List<Note> {
|
||||||
|
return collection
|
||||||
|
.sortedWith(compareBy({ it.createdAt() }, { it.idHex }))
|
||||||
|
.reversed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ abstract class AdditiveFeedFilter<T> : FeedFilter<T>() {
|
|||||||
abstract fun sort(collection: Set<T>): List<T>
|
abstract fun sort(collection: Set<T>): List<T>
|
||||||
|
|
||||||
@OptIn(ExperimentalTime::class)
|
@OptIn(ExperimentalTime::class)
|
||||||
fun updateListWith(oldList: List<T>, newItems: Set<T>): List<T> {
|
open fun updateListWith(oldList: List<T>, newItems: Set<T>): List<T> {
|
||||||
val (feed, elapsed) = measureTimedValue {
|
val (feed, elapsed) = measureTimedValue {
|
||||||
val newItemsToBeAdded = applyFilter(newItems)
|
val newItemsToBeAdded = applyFilter(newItems)
|
||||||
if (newItemsToBeAdded.isNotEmpty()) {
|
if (newItemsToBeAdded.isNotEmpty()) {
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ object NotificationLatestItem : LatestItem() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object MessagesLatestItem {
|
object MessagesLatestItem : LatestItem() {
|
||||||
fun hasNewItems(
|
fun hasNewItems(
|
||||||
account: Account,
|
account: Account,
|
||||||
cache: NotificationCache,
|
cache: NotificationCache,
|
||||||
@@ -178,13 +178,11 @@ object MessagesLatestItem {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
ChatroomListKnownFeedFilter.account = account
|
ChatroomListKnownFeedFilter.account = account
|
||||||
|
|
||||||
val note = ChatroomListKnownFeedFilter.loadTop().firstOrNull {
|
val newestItem = updateNewestItem(newNotes, account, ChatroomListKnownFeedFilter)
|
||||||
it.createdAt() != null && it.channel() == null && it.author != account.userProfile()
|
|
||||||
} ?: return false
|
|
||||||
|
|
||||||
val lastTime = cache.load("Room/${note.author?.pubkeyHex}")
|
val lastTime = cache.load("Room/${newestItem?.author?.pubkeyHex}")
|
||||||
|
|
||||||
return (note.createdAt() ?: 0) > lastTime
|
return (newestItem?.createdAt() ?: 0) > lastTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user