From a52bafbf98a8e54e66d84ad4dec40e96519fbb22 Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 26 Jun 2024 22:37:22 +0930 Subject: [PATCH] SES-2237 Fix search sorting --- .../securesms/home/HomeActivity.kt | 36 +++++++++++++++---- .../home/search/GlobalSearchAdapterUtils.kt | 11 +++--- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index 56d1789b4c..8de6d671e5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -138,8 +138,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), private val globalSearchViewModel by viewModels() private val homeViewModel by viewModels() - private val publicKey: String - get() = textSecurePreferences.getLocalNumber()!! + private val publicKey: String by lazy { textSecurePreferences.getLocalNumber()!! } private val homeAdapter: HomeAdapter by lazy { HomeAdapter(context = this, configFactory = configFactory, listener = this, ::showMessageRequests, ::hideMessageRequests) @@ -289,12 +288,35 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), launch { globalSearchViewModel.result.collect { result -> if (result.query.isEmpty()) { - val hasNames = result.contacts.filter { it.nickname != null || it.name != null } - .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) } + class NamedValue(val name: String, val value: T) - 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 } .map { GlobalSearchAdapter.Model.Contact(it) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt b/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt index d77c8a5d68..1903b13b3b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt @@ -10,6 +10,7 @@ import network.loki.messenger.R import org.session.libsession.messaging.contacts.Contact import org.session.libsession.utilities.Address 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.Model.GroupConversation 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 membersString = groupRecipients.joinToString { - val address = it.address.serialize() - it.name ?: "${address.take(4)}...${address.takeLast(4)}" + it.name ?: truncateIdForDisplay(it.address.serialize()) } if (model.groupRecord.isClosedGroup) { binding.searchResultSubtitle.text = getHighlight(query, membersString) @@ -153,8 +153,7 @@ fun ContentView.bindModel(query: String?, model: Message) { 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 = - if (nickname.isNullOrEmpty()) name ?: "${accountID.take(4)}...${accountID.takeLast(4)}" - else "${name ?: "${accountID.take(4)}...${accountID.takeLast(4)}"} ($nickname)" \ No newline at end of file +fun Contact.getSearchName(): String = nickname?.takeIf { it.isNotEmpty() } + ?: name?.takeIf { it.isNotEmpty() } ?: truncateIdForDisplay(accountID)