mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-26 01:37:43 +00:00
Cleanup search processing
This commit is contained in:
parent
e3a33ea615
commit
38e73cf514
@ -22,6 +22,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import network.loki.messenger.R
|
||||
@ -58,6 +59,7 @@ import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
||||
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter
|
||||
import org.thoughtcrime.securesms.home.search.GlobalSearchInputLayout
|
||||
import org.thoughtcrime.securesms.home.search.GlobalSearchResult
|
||||
import org.thoughtcrime.securesms.home.search.GlobalSearchViewModel
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
@ -239,67 +241,25 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
}
|
||||
// Get group results and display them
|
||||
launch {
|
||||
globalSearchViewModel.result.collect { result ->
|
||||
if (result.query.isEmpty()) {
|
||||
class NamedValue<T>(val name: String?, val value: T)
|
||||
|
||||
// Unknown is temporarily to be grouped together with numbers title.
|
||||
// https://optf.atlassian.net/browse/SES-2287
|
||||
val numbersTitle = "#"
|
||||
val unknownTitle = numbersTitle
|
||||
|
||||
listOf(
|
||||
GlobalSearchAdapter.Model.Header(R.string.contacts),
|
||||
GlobalSearchAdapter.Model.SavedMessages(publicKey)
|
||||
) + 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.
|
||||
.map { (it.nickname?.takeIf(String::isNotEmpty) ?: it.name?.takeIf(String::isNotEmpty))
|
||||
.let { name -> NamedValue(name?.uppercase(), it) } }
|
||||
// Digits are all grouped under a #, the rest are grouped by their first character.uppercased()
|
||||
// If there is no name, they go under Unknown
|
||||
.groupBy { it.name?.run { first().takeUnless(Char::isDigit)?.toString() ?: numbersTitle } ?: unknownTitle }
|
||||
// place the # at the end, after all the names starting with alphabetic chars
|
||||
.toSortedMap(compareBy {
|
||||
when (it) {
|
||||
unknownTitle -> Char.MAX_VALUE
|
||||
numbersTitle -> Char.MAX_VALUE - 1
|
||||
else -> it.first()
|
||||
}
|
||||
})
|
||||
// Flatten the map of char to lists into an actual List that can be displayed.
|
||||
.flatMap { (key, contacts) ->
|
||||
listOf(
|
||||
GlobalSearchAdapter.Model.SubHeader(key)
|
||||
) + contacts.sortedBy { it.name ?: it.value.accountID }.map { it.value }.map { GlobalSearchAdapter.Model.Contact(it, it.nickname ?: it.name, it.accountID == publicKey) }
|
||||
globalSearchViewModel.result.map { result ->
|
||||
result.query to when {
|
||||
result.query.isEmpty() -> buildList {
|
||||
add(GlobalSearchAdapter.Model.Header(R.string.contacts))
|
||||
add(GlobalSearchAdapter.Model.SavedMessages(publicKey))
|
||||
addAll(result.groupedContacts)
|
||||
}
|
||||
else -> buildList {
|
||||
result.contactAndGroupList.takeUnless { it.isEmpty() }?.let {
|
||||
add(GlobalSearchAdapter.Model.Header(R.string.contacts))
|
||||
addAll(it)
|
||||
}
|
||||
result.messageResults.takeUnless { it.isEmpty() }?.let {
|
||||
add(GlobalSearchAdapter.Model.Header(R.string.global_search_messages))
|
||||
addAll(it)
|
||||
}
|
||||
} else {
|
||||
val contactAndGroupList = result.contacts.map { GlobalSearchAdapter.Model.Contact(it, it.nickname ?: it.name, it.accountID == publicKey) } +
|
||||
result.threads.map(GlobalSearchAdapter.Model::GroupConversation)
|
||||
|
||||
val contactResults = contactAndGroupList.toMutableList()
|
||||
|
||||
if (contactResults.isNotEmpty()) {
|
||||
contactResults.add(0, GlobalSearchAdapter.Model.Header(R.string.conversations))
|
||||
}
|
||||
|
||||
val unreadThreadMap = result.messages
|
||||
.map { it.threadId }.toSet()
|
||||
.associateWith { mmsSmsDatabase.getUnreadCount(it) }
|
||||
|
||||
val messageResults: MutableList<GlobalSearchAdapter.Model> = result.messages
|
||||
.map { GlobalSearchAdapter.Model.Message(it, unreadThreadMap[it.threadId] ?: 0, it.conversationRecipient.isLocalNumber) }
|
||||
.toMutableList()
|
||||
|
||||
if (messageResults.isNotEmpty()) {
|
||||
messageResults.add(0, GlobalSearchAdapter.Model.Header(R.string.global_search_messages))
|
||||
}
|
||||
|
||||
contactResults + messageResults
|
||||
}.let { globalSearchAdapter.setNewData(result.query, it) }
|
||||
}
|
||||
}
|
||||
}.collectLatest(globalSearchAdapter::setNewData)
|
||||
}
|
||||
}
|
||||
EventBus.getDefault().register(this@HomeActivity)
|
||||
@ -317,6 +277,54 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
}
|
||||
}
|
||||
|
||||
private val GlobalSearchResult.groupedContacts: List<GlobalSearchAdapter.Model> get() {
|
||||
class NamedValue<T>(val name: String?, val value: T)
|
||||
|
||||
// Unknown is temporarily to be grouped together with numbers title.
|
||||
// https://optf.atlassian.net/browse/SES-2287
|
||||
val numbersTitle = "#"
|
||||
val unknownTitle = numbersTitle
|
||||
|
||||
return 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.
|
||||
.map { (it.nickname?.takeIf(String::isNotEmpty) ?: it.name?.takeIf(String::isNotEmpty))
|
||||
.let { name -> NamedValue(name?.uppercase(), it) } }
|
||||
// Digits are all grouped under a #, the rest are grouped by their first character.uppercased()
|
||||
// If there is no name, they go under Unknown
|
||||
.groupBy { it.name?.run { first().takeUnless(Char::isDigit)?.toString() ?: numbersTitle } ?: unknownTitle }
|
||||
// place the # at the end, after all the names starting with alphabetic chars
|
||||
.toSortedMap(compareBy {
|
||||
when (it) {
|
||||
unknownTitle -> Char.MAX_VALUE
|
||||
numbersTitle -> Char.MAX_VALUE - 1
|
||||
else -> it.first()
|
||||
}
|
||||
})
|
||||
// Flatten the map of char to lists into an actual List that can be displayed.
|
||||
.flatMap { (key, contacts) ->
|
||||
listOf(
|
||||
GlobalSearchAdapter.Model.SubHeader(key)
|
||||
) + contacts.sortedBy { it.name ?: it.value.accountID }.map { it.value }.map { GlobalSearchAdapter.Model.Contact(it, it.nickname ?: it.name, it.accountID == publicKey) }
|
||||
}
|
||||
}
|
||||
|
||||
private val GlobalSearchResult.contactAndGroupList: List<GlobalSearchAdapter.Model> get() =
|
||||
contacts.map { GlobalSearchAdapter.Model.Contact(it, it.nickname ?: it.name, it.accountID == publicKey) } +
|
||||
threads.map(GlobalSearchAdapter.Model::GroupConversation)
|
||||
|
||||
private val GlobalSearchResult.messageResults: List<GlobalSearchAdapter.Model> get() {
|
||||
val unreadThreadMap = messages
|
||||
.map { it.threadId }.toSet()
|
||||
.associateWith { mmsSmsDatabase.getUnreadCount(it) }
|
||||
|
||||
return messages.map {
|
||||
GlobalSearchAdapter.Model.Message(it, unreadThreadMap[it.threadId] ?: 0, it.conversationRecipient.isLocalNumber)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInputFocusChanged(hasFocus: Boolean) {
|
||||
setSearchShown(hasFocus || binding.globalSearchInputLayout.query.value.isNotEmpty())
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ class GlobalSearchAdapter(private val modelCallback: (Model)->Unit): RecyclerVie
|
||||
private var data: List<Model> = listOf()
|
||||
private var query: String? = null
|
||||
|
||||
fun setNewData(data: Pair<String, List<Model>>) = setNewData(data.first, data.second)
|
||||
|
||||
fun setNewData(query: String, newData: List<Model>) {
|
||||
val diffResult = DiffUtil.calculateDiff(GlobalSearchDiff(this.query, query, data, newData))
|
||||
this.query = query
|
||||
|
Loading…
x
Reference in New Issue
Block a user