Refresh contacts on open

pr/1451-buttons
Andrew 11 months ago
parent cad96001d1
commit 853c165949

@ -206,6 +206,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
// Set up toolbar buttons
binding.profileButton.setOnClickListener { openSettings() }
binding.searchViewContainer.setOnClickListener {
globalSearchViewModel.refresh()
binding.globalSearchInputLayout.requestFocus()
}
binding.sessionToolbar.disableClipping()
@ -287,29 +288,25 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
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.map(GlobalSearchAdapter.Model::Contact) }
.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 }
.sortedBy { it.sessionID }
.map { GlobalSearchAdapter.Model.Contact(it) }
.takeIf { it.isNotEmpty() }
?.let {
buildList {
add(GlobalSearchAdapter.Model.Header("Unknown"))
addAll(it)
}
} ?: emptyList()
buildList {
add(GlobalSearchAdapter.Model.Header("Contacts"))
add(GlobalSearchAdapter.Model.Header(R.string.contacts))
add(GlobalSearchAdapter.Model.SavedMessages(publicKey))
addAll(hasNames)
addAll(noNames)
noNames.takeIf { it.isNotEmpty() }?.let {
add(GlobalSearchAdapter.Model.Header(R.string.unknown))
addAll(it)
}
}
} else {
val currentUserPublicKey = publicKey
val contactAndGroupList = result.contacts.map { GlobalSearchAdapter.Model.Contact(it) } +
result.threads.map { GlobalSearchAdapter.Model.GroupConversation(it) }
val contactAndGroupList = result.contacts.map(GlobalSearchAdapter.Model::Contact) +
result.threads.map(GlobalSearchAdapter.Model::GroupConversation)
val contactResults = contactAndGroupList.toMutableList()
@ -323,7 +320,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
}
if (contactResults.isNotEmpty()) {
contactResults.add(0, GlobalSearchAdapter.Model.Header(R.string.global_search_contacts_groups))
contactResults.add(0, GlobalSearchAdapter.Model.Header(R.string.conversations))
}
val unreadThreadMap = result.messages
@ -393,7 +390,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
Spacer(Modifier.width(12.dp))
OutlineButton(
textId = R.string.continue_2,
Modifier.align(Alignment.CenterVertically)
Modifier
.align(Alignment.CenterVertically)
.contentDescription(R.string.AccessibilityId_reveal_recovery_phrase_button),
onClick = { start<RecoveryPasswordActivity>() }
)

@ -3,19 +3,27 @@ package org.thoughtcrime.securesms.home.search
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
import org.session.libsession.utilities.truncateIdForDisplay
import org.session.libsignal.utilities.SettableFuture
import org.thoughtcrime.securesms.database.SessionContactDatabase
import org.thoughtcrime.securesms.search.SearchRepository
import org.thoughtcrime.securesms.search.model.SearchResult
import java.util.concurrent.TimeUnit
@ -32,6 +40,8 @@ class GlobalSearchViewModel @Inject constructor(
val result: StateFlow<GlobalSearchResult> = _result
val refreshes = Channel<Unit>()
private val _queryText: MutableStateFlow<CharSequence> = MutableStateFlow("")
fun postQuery(charSequence: CharSequence?) {
@ -39,14 +49,22 @@ class GlobalSearchViewModel @Inject constructor(
_queryText.value = charSequence
}
fun refresh() {
executor.launch { refreshes.send(Unit) }
}
init {
_queryText.buffer(onBufferOverflow = BufferOverflow.DROP_OLDEST)
_queryText
.reEmit(refreshes)
.buffer(onBufferOverflow = BufferOverflow.DROP_OLDEST)
.mapLatest { query ->
// User input delay in case we get a new query within a few hundred ms this
// coroutine will be cancelled and the expensive query will not be run.
delay(300)
if (query.trim().isEmpty()) {
// searching for 05 as contactDb#getAllContacts was not returning contacts
// without a nickname/name who haven't approved us.
GlobalSearchResult(query.toString(), searchRepository.queryContacts("05").first.toList())
} else {
val settableFuture = SettableFuture<SearchResult>()
@ -64,3 +82,9 @@ class GlobalSearchViewModel @Inject constructor(
}.launchIn(executor)
}
}
/**
* Re-emit whenevr refreshes emits.
* */
@OptIn(ExperimentalCoroutinesApi::class)
private fun <T> Flow<T>.reEmit(refreshes: Channel<Unit>) = flatMapLatest { query -> merge(flowOf(query), refreshes.consumeAsFlow().map { query }) }

Loading…
Cancel
Save