Merge pull request #2052 from vitorpamplona/claude/fix-sorting-order-p23ZY

Improve sorting stability by adding secondary sort keys
This commit is contained in:
Vitor Pamplona
2026-03-31 08:42:46 -04:00
committed by GitHub
8 changed files with 14 additions and 18 deletions
@@ -75,5 +75,5 @@ open class DiscoverMarketplaceFeedFilter(
} }
} }
override fun sort(items: Set<Note>): List<Note> = items.sortedWith(compareBy({ it.createdAt() }, { it.idHex })).reversed() override fun sort(items: Set<Note>): List<Note> = items.sortedWith(compareByDescending<Note> { it.createdAt() }.thenBy { it.idHex })
} }
@@ -262,8 +262,7 @@ class CardFeedContentState(
val sortedList = val sortedList =
singleList singleList
.get(string) .get(string)
?.sortedWith(compareBy({ it.createdAt() }, { it.idHex })) ?.sortedWith(compareByDescending<Note> { it.createdAt() }.thenBy { it.idHex })
?.reversed()
sortedList?.chunked(30)?.map { chunk -> sortedList?.chunked(30)?.map { chunk ->
MultiSetCard( MultiSetCard(
@@ -293,8 +292,7 @@ class CardFeedContentState(
ZapUserSetCard( ZapUserSetCard(
user.key, user.key,
zaps zaps
.sortedWith(compareBy({ it.createdAt() }, { it.idHex() })) .sortedWith(compareByDescending<Note> { it.createdAt() }.thenBy { it.idHex() })
.reversed()
.toImmutableList(), .toImmutableList(),
) )
} }
@@ -318,8 +316,7 @@ class CardFeedContentState(
} }
return (multiCards + textNoteCards + userZaps) return (multiCards + textNoteCards + userZaps)
.sortedWith(compareBy({ it.createdAt() }, { it.id() })) .sortedWith(compareByDescending<Card> { it.createdAt() }.thenBy { it.id() })
.reversed()
} }
private fun updateFeed(notes: ImmutableList<Card>) { private fun updateFeed(notes: ImmutableList<Card>) {
@@ -383,8 +380,7 @@ class CardFeedContentState(
val updatedCards = val updatedCards =
(oldNotesState.feed.value.list + newCards) (oldNotesState.feed.value.list + newCards)
.distinctBy { it.id() } .distinctBy { it.id() }
.sortedWith(compareBy({ it.createdAt() }, { it.id() })) .sortedWith(compareByDescending<Card> { it.createdAt() }.thenBy { it.id() })
.reversed()
.take(localFilter.limit()) .take(localFilter.limit())
.toImmutableList() .toImmutableList()
@@ -80,6 +80,6 @@ class OpenPollsState(
false false
} }
} }
}.sortedByDescending { it.createdAt() } }.sortedWith(compareByDescending<Note> { it.createdAt() }.thenBy { it.idHex })
} }
} }
@@ -53,7 +53,7 @@ object SearchResultFilter {
} }
// Sort by createdAt descending // Sort by createdAt descending
return result.sortedByDescending { it.createdAt } return result.sortedWith(compareByDescending<Event> { it.createdAt }.thenBy { it.id })
} }
fun isReply(event: Event): Boolean = event.kind == 1 && event.tags.any { it.size >= 2 && it[0] == "e" } fun isReply(event: Event): Boolean = event.kind == 1 && event.tags.any { it.size >= 2 && it[0] == "e" }
@@ -33,16 +33,16 @@ object SearchResultSorter {
): List<Event> = ): List<Event> =
when (order) { when (order) {
SearchSortOrder.NEWEST -> { SearchSortOrder.NEWEST -> {
events.sortedByDescending { it.createdAt } events.sortedWith(compareByDescending<Event> { it.createdAt }.thenBy { it.id })
} }
SearchSortOrder.OLDEST -> { SearchSortOrder.OLDEST -> {
events.sortedBy { it.createdAt } events.sortedWith(compareBy<Event> { it.createdAt }.thenBy { it.id })
} }
SearchSortOrder.RELEVANCE -> { SearchSortOrder.RELEVANCE -> {
if (searchText.isBlank()) { if (searchText.isBlank()) {
events.sortedByDescending { it.createdAt } events.sortedWith(compareByDescending<Event> { it.createdAt }.thenBy { it.id })
} else { } else {
events.sortedByDescending { scoreEvent(it, searchText) } events.sortedByDescending { scoreEvent(it, searchText) }
} }
@@ -75,4 +75,4 @@ sealed class CardFeedState {
*/ */
val DefaultCardComparator: Comparator<Card> = val DefaultCardComparator: Comparator<Card> =
compareByDescending<Card> { it.createdAt() } compareByDescending<Card> { it.createdAt() }
.thenByDescending { it.id() } .thenBy { it.id() }
@@ -196,7 +196,7 @@ fun ReadsScreen(
remember { remember {
EventCollectionState<LongTextNoteEvent>( EventCollectionState<LongTextNoteEvent>(
getId = { it.id }, getId = { it.id },
sortComparator = compareByDescending { it.publishedAt() ?: it.createdAt }, sortComparator = compareByDescending<LongTextNoteEvent> { it.publishedAt() ?: it.createdAt }.thenBy { it.id },
maxSize = 100, maxSize = 100,
scope = scope, scope = scope,
) )
@@ -829,7 +829,7 @@ fun UserProfileScreen(
} }
} else { } else {
items( items(
articleEvents.sortedByDescending { it.publishedAt() ?: it.createdAt }, articleEvents.sortedWith(compareByDescending<LongTextNoteEvent> { it.publishedAt() ?: it.createdAt }.thenBy { it.id }),
key = { "art-${it.id}" }, key = { "art-${it.id}" },
) { article -> ) { article ->
LongFormCard( LongFormCard(
@@ -871,7 +871,7 @@ fun UserProfileScreen(
} }
} else { } else {
items( items(
highlightEvents.sortedByDescending { it.createdAt }, highlightEvents.sortedWith(compareByDescending<HighlightEvent> { it.createdAt }.thenBy { it.id }),
key = { "hl-${it.id}" }, key = { "hl-${it.id}" },
) { highlight -> ) { highlight ->
PublishedHighlightCard( PublishedHighlightCard(