diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index c016cd4a8..b65847756 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -32,11 +32,11 @@ import com.vitorpamplona.amethyst.commons.model.privateChats.ChatroomList import com.vitorpamplona.amethyst.commons.services.nwc.NwcPaymentTracker import com.vitorpamplona.amethyst.isDebug import com.vitorpamplona.amethyst.model.nip51Lists.HiddenUsersState +import com.vitorpamplona.amethyst.model.observables.CreatedAtIdHexComparator import com.vitorpamplona.amethyst.model.observables.EventListMatchingFilter import com.vitorpamplona.amethyst.model.observables.NoteListMatchingFilter import com.vitorpamplona.amethyst.service.BundledInsert import com.vitorpamplona.amethyst.service.checkNotInMainThread -import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder import com.vitorpamplona.amethyst.ui.note.dateFormatter import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent @@ -307,7 +307,7 @@ object LocalCache : ILocalCache, ICacheProvider { (addressableMatches + noteMatches) } - return limitedSet.toSortedSet(DefaultFeedOrder) + return limitedSet.toSortedSet(CreatedAtIdHexComparator) } fun observeNotes(filter: Filter): Flow> = diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/CreatedAtComparator.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/CreatedAtComparator.kt index c13a4be33..f6350acf9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/CreatedAtComparator.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/CreatedAtComparator.kt @@ -23,6 +23,32 @@ package com.vitorpamplona.amethyst.model.observables import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.model.Note +val CreatedAtIdHexComparator: Comparator = + Comparator { note1, note2 -> + // Sort by created_at and idhex, but define uniqueness by reference + if (note1 === note2) return@Comparator 0 + + if (note1 == null) return@Comparator 1 // null is greater, moves to last + if (note2 == null) return@Comparator -1 // null is greater, moves to last + + val createdAt1 = note1.createdAt() + val createdAt2 = note2.createdAt() + + if (createdAt1 == createdAt2) { + val event1 = note1.event + val event2 = note2.event + + if (event1 == null && event2 == null) return@Comparator 0 + if (event1 == null) return@Comparator 1 // null is greater, moves to last + if (event2 == null) return@Comparator -1 // null is greater, moves to last + + event1.id.compareTo(event2.id) + } else { + // Descending, inverts + compareValues(createdAt2, createdAt1) + } + } + object CreatedAtComparator : Comparator { override fun compare( first: Note?, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/EventListMatchingFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/EventListMatchingFilter.kt index 4534d1dda..db13754c4 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/EventListMatchingFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/EventListMatchingFilter.kt @@ -23,10 +23,9 @@ package com.vitorpamplona.amethyst.model.observables import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Observable -import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter -import java.util.SortedSet +import java.util.concurrent.ConcurrentSkipListSet /** * Creates a list of events (regular and addressable) @@ -39,7 +38,7 @@ class EventListMatchingFilter( private val update: (List) -> Unit, ) : Observable { // Keeping this here blocks it from being cleared from memory - var currentResults: SortedSet = sortedSetOf(DefaultFeedOrder) + var currentResults: ConcurrentSkipListSet = ConcurrentSkipListSet(CreatedAtIdHexComparator) override fun new( event: Event, @@ -51,6 +50,7 @@ class EventListMatchingFilter( if (limit != null && currentResults.size > limit) { currentResults.remove(currentResults.last()) } + update(currentResults.mapNotNull { it.event }) } } @@ -62,7 +62,7 @@ class EventListMatchingFilter( } fun init() { - currentResults = cache.filter(filter) + currentResults = ConcurrentSkipListSet(cache.filter(filter)) update(currentResults.mapNotNull { it.event }) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/NoteListMatchingFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/NoteListMatchingFilter.kt index cc4d17f7f..7c3ca5922 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/NoteListMatchingFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/observables/NoteListMatchingFilter.kt @@ -23,10 +23,9 @@ package com.vitorpamplona.amethyst.model.observables import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Observable -import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter -import java.util.SortedSet +import java.util.concurrent.ConcurrentSkipListSet /** * Creates a list of notes (regular and addressable) @@ -39,7 +38,7 @@ class NoteListMatchingFilter( private val cache: LocalCache, private val update: (List) -> Unit, ) : Observable { - var currentResults: SortedSet = sortedSetOf(DefaultFeedOrder) + var currentResults: ConcurrentSkipListSet = ConcurrentSkipListSet(CreatedAtIdHexComparator) override fun new( event: Event, @@ -64,7 +63,7 @@ class NoteListMatchingFilter( } fun init() { - currentResults = cache.filter(filter) + currentResults = ConcurrentSkipListSet(cache.filter(filter)) update(currentResults.toList()) } }