Skip to content

Commit

Permalink
Debounce performing search depending on searchquery length
Browse files Browse the repository at this point in the history
  • Loading branch information
LZRS committed Oct 28, 2024
1 parent 64a55e6 commit 59afd74
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ import com.google.android.fhir.sync.CurrentSyncJobStatus
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlin.math.ceil
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -78,10 +81,12 @@ import org.smartregister.fhircore.engine.util.SharedPreferencesHelper
import org.smartregister.fhircore.engine.util.extension.encodeJson
import org.smartregister.fhircore.quest.data.register.RegisterPagingSource
import org.smartregister.fhircore.quest.data.register.model.RegisterPagingSourceState
import org.smartregister.fhircore.quest.ui.shared.models.SearchQuery
import org.smartregister.fhircore.quest.util.extensions.referenceToBitmap
import org.smartregister.fhircore.quest.util.extensions.toParamDataMap
import timber.log.Timber

@OptIn(FlowPreview::class)
@HiltViewModel
class RegisterViewModel
@Inject
Expand Down Expand Up @@ -112,6 +117,27 @@ constructor(
}
private val decodedImageMap = mutableStateMapOf<String, Bitmap>()

private val _searchQueryFlow: MutableSharedFlow<SearchQuery> = MutableSharedFlow()

init {
viewModelScope.launch {
_searchQueryFlow
.debounce {
val searchText = it.query
when (searchText.length) {
0 -> 2.milliseconds // when search is cleared
1,
2, -> 1000.milliseconds
else -> 500.milliseconds
}
}
.collect {
val registerId = registerUiState.value.registerId
performSearch(registerId, it)
}
}
}

/**
* This function paginates the register data. An optional [clearCache] resets the data in the
* cache (this is necessary after a questionnaire has been submitted to refresh the register with
Expand Down Expand Up @@ -191,26 +217,7 @@ constructor(
when (event) {
// Search using name or patient logicalId or identifier. Modify to add more search params
is RegisterEvent.SearchRegister -> {
if (event.searchQuery.isBlank()) {
val regConfig = retrieveRegisterConfiguration(registerId)
val searchByDynamicQueries = !regConfig.searchBar?.dataFilterFields.isNullOrEmpty()
if (searchByDynamicQueries) {
registerFilterState.value = RegisterFilterState() // Reset queries
}
when {
regConfig.infiniteScroll ->
registerData.value = retrieveCompleteRegisterData(registerId, searchByDynamicQueries)
else ->
retrieveRegisterUiState(
registerId = registerId,
screenTitle = registerUiState.value.screenTitle,
params = registerUiState.value.params.toTypedArray(),
clearCache = searchByDynamicQueries,
)
}
} else {
filterRegisterData(event.searchQuery.query)
}
viewModelScope.launch { _searchQueryFlow.emit(event.searchQuery) }
}
is RegisterEvent.MoveToNextPage -> {
currentPage.value = currentPage.value.plus(1)
Expand All @@ -224,6 +231,29 @@ constructor(
}
}

private fun performSearch(registerId: String, searchQuery: SearchQuery) {
if (searchQuery.isBlank()) {
val regConfig = retrieveRegisterConfiguration(registerId)
val searchByDynamicQueries = !regConfig.searchBar?.dataFilterFields.isNullOrEmpty()
if (searchByDynamicQueries) {
registerFilterState.value = RegisterFilterState() // Reset queries
}
when {
regConfig.infiniteScroll ->
registerData.value = retrieveCompleteRegisterData(registerId, searchByDynamicQueries)
else ->
retrieveRegisterUiState(
registerId = registerId,
screenTitle = registerUiState.value.screenTitle,
params = registerUiState.value.params.toTypedArray(),
clearCache = searchByDynamicQueries,
)
}
} else {
filterRegisterData(searchQuery.query)
}
}

fun filterRegisterData(searchText: String) {
val searchBar = registerUiState.value.registerConfiguration?.searchBar
val registerId = registerUiState.value.registerId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,16 @@ class RegisterViewModelTest : RobolectricTest() {
@Test
@kotlinx.coroutines.ExperimentalCoroutinesApi
fun testRetrieveRegisterUiState() = runTest {
every { registerViewModel.retrieveRegisterConfiguration(any()) } returns
val registerConfig =
RegisterConfiguration(
appId = "app",
id = registerId,
fhirResource =
FhirResourceConfig(baseResource = ResourceConfig(resource = ResourceType.Patient)),
pageSize = 10,
)
configurationRegistry.configCacheMap[registerId] = registerConfig

every { registerViewModel.paginateRegisterData(any(), any()) } just runs
coEvery { registerRepository.countRegisterData(any()) } returns 200
registerViewModel.retrieveRegisterUiState(
Expand All @@ -143,17 +145,20 @@ class RegisterViewModelTest : RobolectricTest() {
}

@Test
fun testOnEventSearchRegister() {
every { registerViewModel.retrieveRegisterConfiguration(any()) } returns
fun testOnEventSearchRegister() = runTest {
val registerConfig =
RegisterConfiguration(
appId = "app",
id = registerId,
fhirResource =
FhirResourceConfig(baseResource = ResourceConfig(resource = ResourceType.Patient)),
pageSize = 10,
)
every { registerViewModel.registerUiState } returns
mutableStateOf(RegisterUiState(registerId = registerId))
configurationRegistry.configCacheMap[registerId] = registerConfig
registerViewModel.registerUiState.value =
registerViewModel.registerUiState.value.copy(registerId = registerId)
coEvery { registerRepository.countRegisterData(any()) } returns 0L

// Search with empty string should paginate the data
registerViewModel.onEvent(RegisterEvent.SearchRegister(SearchQuery.emptyText))
verify { registerViewModel.retrieveRegisterUiState(any(), any(), any(), any()) }
Expand Down

0 comments on commit 59afd74

Please sign in to comment.