Cleanup GlobalSearchViewModel

This commit is contained in:
bemusementpark
2024-07-12 11:48:39 +09:30
parent cb8b9d63ac
commit afe1295289
2 changed files with 26 additions and 43 deletions

View File

@@ -8,7 +8,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.Telephony.Mms.Addr
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.os.bundleOf import androidx.core.os.bundleOf

View File

@@ -6,22 +6,18 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.plus import kotlinx.coroutines.plus
import org.session.libsignal.utilities.SettableFuture import org.session.libsignal.utilities.SettableFuture
@@ -35,16 +31,32 @@ import javax.inject.Inject
class GlobalSearchViewModel @Inject constructor( class GlobalSearchViewModel @Inject constructor(
private val searchRepository: SearchRepository, private val searchRepository: SearchRepository,
) : ViewModel() { ) : ViewModel() {
private val scope = viewModelScope + SupervisorJob()
private val executor = viewModelScope + SupervisorJob()
private val _result: MutableStateFlow<GlobalSearchResult> = MutableStateFlow(GlobalSearchResult.EMPTY)
val result: StateFlow<GlobalSearchResult> = _result
private val refreshes = MutableSharedFlow<Unit>() private val refreshes = MutableSharedFlow<Unit>()
private val _queryText = MutableStateFlow<CharSequence>("")
private val _queryText: MutableStateFlow<CharSequence> = MutableStateFlow("") val result = _queryText
.reEmit(refreshes)
.buffer(onBufferOverflow = BufferOverflow.DROP_OLDEST)
.mapLatest { query ->
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 {
// 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)
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).toGlobalSearchResult()
} catch (e: Exception) {
GlobalSearchResult(query.toString())
}
}
}.stateIn(scope, SharingStarted.Lazily, GlobalSearchResult.EMPTY)
fun setQuery(charSequence: CharSequence) { fun setQuery(charSequence: CharSequence) {
_queryText.value = charSequence _queryText.value = charSequence
@@ -55,34 +67,6 @@ class GlobalSearchViewModel @Inject constructor(
refreshes.emit(Unit) refreshes.emit(Unit)
} }
} }
init {
_queryText
.reEmit(refreshes)
.buffer(onBufferOverflow = BufferOverflow.DROP_OLDEST)
.mapLatest { query ->
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 {
// 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)
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).toGlobalSearchResult()
} catch (e: Exception) {
GlobalSearchResult(query.toString())
}
}
}.onEach { result ->
// update the latest _result value
_result.value = result
}.launchIn(executor)
}
} }
/** /**