mirror of
https://github.com/oxen-io/session-android.git
synced 2023-12-14 02:53:01 +01:00
dd1da6b1a4
* feat: modifying search functionalities to include contacts * feat: add global search UI input layouts and color attributes * feat: add global search repository and model content * feat: adding diff callbacks and wiring up global search vm to views * feat: adding scroll to message, figuring out new query for recipient thread search * feat: messing with the search and highlighting functionality after wiring up bindings * fix: compile error from merge * fix: gradlew build errors * feat: filtering contacts by existing un-archived threads * refactor: prevent note to self breaking, update queries and logic in search repo to include member->group reverse searches * feat: adding home screen new redesigns for search * feat: replacing designs and adding new group subtitle text * feat: small design improvements and incrementing gradle build number to install on device * feat: add scrollbars for search * feat: replace isVisible for cancel button now that GlobalSearchInputLayout.kt replaces header * refactor: all queries are debounced not just all but 2 char * refactor: remove visibility modifiers for cancel icon * refactor: use simplified non-db and context related models in display, remove db get group members call from binding data * fix: use threadId instead of group's address * refactor: better close on cancel, removing only yourself from group member list in open groups * refactor: seed view back to inflated on create and visibility for empty placeholder and seed view text * refactor: fixing build issues and new designs for message list * refactor: use dynamic limit * refactor: include raw session ID string search for non-empty threads * fix: build lint errors * fix: build issues * feat: add in path to the settings activity * refactor: remove wildcard imports
69 lines
2.7 KiB
Kotlin
69 lines
2.7 KiB
Kotlin
package org.thoughtcrime.securesms.home.search
|
|
|
|
import androidx.lifecycle.ViewModel
|
|
import androidx.lifecycle.viewModelScope
|
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
|
import kotlinx.coroutines.SupervisorJob
|
|
import kotlinx.coroutines.channels.BufferOverflow
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.flow.MutableStateFlow
|
|
import kotlinx.coroutines.flow.StateFlow
|
|
import kotlinx.coroutines.flow.buffer
|
|
import kotlinx.coroutines.flow.launchIn
|
|
import kotlinx.coroutines.flow.mapLatest
|
|
import kotlinx.coroutines.flow.onEach
|
|
import kotlinx.coroutines.plus
|
|
import org.session.libsignal.utilities.SettableFuture
|
|
import org.thoughtcrime.securesms.search.SearchRepository
|
|
import org.thoughtcrime.securesms.search.model.SearchResult
|
|
import java.util.concurrent.TimeUnit
|
|
import javax.inject.Inject
|
|
|
|
@HiltViewModel
|
|
class GlobalSearchViewModel @Inject constructor(private val searchRepository: SearchRepository) : ViewModel() {
|
|
|
|
private val executor = viewModelScope + SupervisorJob()
|
|
|
|
private val _result: MutableStateFlow<GlobalSearchResult> =
|
|
MutableStateFlow(GlobalSearchResult.EMPTY)
|
|
|
|
val result: StateFlow<GlobalSearchResult> = _result
|
|
|
|
private val _queryText: MutableStateFlow<CharSequence> = MutableStateFlow("")
|
|
|
|
fun postQuery(charSequence: CharSequence?) {
|
|
charSequence ?: return
|
|
_queryText.value = charSequence
|
|
}
|
|
|
|
init {
|
|
//
|
|
_queryText
|
|
.buffer(onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
|
.mapLatest { query ->
|
|
if (query.trim().length < 2) {
|
|
SearchResult.EMPTY
|
|
} else {
|
|
// user input delay here in case we get a new query within a few hundred ms
|
|
// this coroutine will be cancelled and expensive query will not be run if typing quickly
|
|
// first query of 2 characters will be instant however
|
|
delay(300)
|
|
val settableFuture = SettableFuture<SearchResult>()
|
|
searchRepository.query(query.toString(), settableFuture::set)
|
|
try {
|
|
// search repository doesn't play nicely with suspend functions (yet)
|
|
settableFuture.get(10_000, TimeUnit.MILLISECONDS)
|
|
} catch (e: Exception) {
|
|
SearchResult.EMPTY
|
|
}
|
|
}
|
|
}
|
|
.onEach { result ->
|
|
// update the latest _result value
|
|
_result.value = GlobalSearchResult.from(result)
|
|
}
|
|
.launchIn(executor)
|
|
}
|
|
|
|
|
|
} |