SES-2237 Fix search sorting

This commit is contained in:
Andrew 2024-06-26 22:37:22 +09:30
parent 84efcd2f21
commit a52bafbf98
2 changed files with 34 additions and 13 deletions

View File

@ -138,8 +138,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
private val globalSearchViewModel by viewModels<GlobalSearchViewModel>() private val globalSearchViewModel by viewModels<GlobalSearchViewModel>()
private val homeViewModel by viewModels<HomeViewModel>() private val homeViewModel by viewModels<HomeViewModel>()
private val publicKey: String private val publicKey: String by lazy { textSecurePreferences.getLocalNumber()!! }
get() = textSecurePreferences.getLocalNumber()!!
private val homeAdapter: HomeAdapter by lazy { private val homeAdapter: HomeAdapter by lazy {
HomeAdapter(context = this, configFactory = configFactory, listener = this, ::showMessageRequests, ::hideMessageRequests) HomeAdapter(context = this, configFactory = configFactory, listener = this, ::showMessageRequests, ::hideMessageRequests)
@ -289,12 +288,35 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
launch { launch {
globalSearchViewModel.result.collect { result -> globalSearchViewModel.result.collect { result ->
if (result.query.isEmpty()) { if (result.query.isEmpty()) {
val hasNames = result.contacts.filter { it.nickname != null || it.name != null } class NamedValue<T>(val name: String, val value: T)
.groupByNotNull { (it.nickname?.firstOrNull() ?: it.name?.firstOrNull())?.uppercase() }
.toSortedMap(compareBy { it })
.flatMap { (key, contacts) -> listOf(GlobalSearchAdapter.Model.SubHeader(key)) + contacts.sortedBy { it.nickname ?: it.name }.map(GlobalSearchAdapter.Model::Contact) }
val noNames = result.contacts.filter { it.nickname == null && it.name == null } val hasNames = result.contacts
// Remove ourself, we're shown above.
.filter { it.accountID != publicKey }
// Get the name that we will display and sort by, and uppercase it to
// help with sorting and we need the char uppercased later.
.mapNotNull { (it.nickname?.takeIf { it.isNotEmpty() } ?: it.name?.takeIf { it.isNotEmpty() })
?.let { name -> NamedValue(name.uppercase(), it) } }
// Digits are all grouped under a #, the rest are grouped by their first character.uppercased()
.groupBy { (it.name.first().takeUnless(Char::isDigit) ?: '#') }
// place the # at the end, after all the names starting with alphabetic chars
.toSortedMap(compareBy {
when (it) {
'#' -> Char.MAX_VALUE - 1
else -> it
}
})
// Flatten the map of char to lists into an actual List that can be displayed.
.flatMap { (key, contacts) ->
listOf(
GlobalSearchAdapter.Model.SubHeader(key.toString())
) + contacts.sortedBy { it.name }.map { it.value }.map(GlobalSearchAdapter.Model::Contact)
}
// Similarly we want to display
val noNames = result.contacts
.filter { it.accountID != publicKey }
.filter { it.nickname.isNullOrEmpty() && it.name.isNullOrEmpty() }
.sortedBy { it.accountID } .sortedBy { it.accountID }
.map { GlobalSearchAdapter.Model.Contact(it) } .map { GlobalSearchAdapter.Model.Contact(it) }

View File

@ -10,6 +10,7 @@ import network.loki.messenger.R
import org.session.libsession.messaging.contacts.Contact import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.utilities.Address import org.session.libsession.utilities.Address
import org.session.libsession.utilities.recipients.Recipient import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.truncateIdForDisplay
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.ContentView import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.ContentView
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.GroupConversation import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.GroupConversation
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.Header import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.Header
@ -100,8 +101,7 @@ fun ContentView.bindModel(query: String?, model: GroupConversation) {
val groupRecipients = model.groupRecord.members.map { Recipient.from(binding.root.context, it, false) } val groupRecipients = model.groupRecord.members.map { Recipient.from(binding.root.context, it, false) }
val membersString = groupRecipients.joinToString { val membersString = groupRecipients.joinToString {
val address = it.address.serialize() it.name ?: truncateIdForDisplay(it.address.serialize())
it.name ?: "${address.take(4)}...${address.takeLast(4)}"
} }
if (model.groupRecord.isClosedGroup) { if (model.groupRecord.isClosedGroup) {
binding.searchResultSubtitle.text = getHighlight(query, membersString) binding.searchResultSubtitle.text = getHighlight(query, membersString)
@ -153,8 +153,7 @@ fun ContentView.bindModel(query: String?, model: Message) {
binding.searchResultSubtitle.isVisible = true binding.searchResultSubtitle.isVisible = true
} }
fun Recipient.getSearchName(): String = name ?: address.serialize().let { address -> "${address.take(4)}...${address.takeLast(4)}" } fun Recipient.getSearchName(): String = name ?: address.serialize().let(::truncateIdForDisplay)
fun Contact.getSearchName(): String = fun Contact.getSearchName(): String = nickname?.takeIf { it.isNotEmpty() }
if (nickname.isNullOrEmpty()) name ?: "${accountID.take(4)}...${accountID.takeLast(4)}" ?: name?.takeIf { it.isNotEmpty() } ?: truncateIdForDisplay(accountID)
else "${name ?: "${accountID.take(4)}...${accountID.takeLast(4)}"} ($nickname)"