From c952dd0686e01c95ceca09f4fa51a6dfc8488495 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Tue, 6 Sep 2022 20:25:14 -0700 Subject: [PATCH] track search results order to make sure old queries aren't displayed --- .../omnivore/ui/home/HomeViewModel.kt | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt index fdc4c2671..7b1f47bcf 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeViewModel.kt @@ -2,7 +2,9 @@ package app.omnivore.omnivore.ui.home import android.util.Log import androidx.core.net.toUri -import androidx.lifecycle.* +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import app.omnivore.omnivore.Constants import app.omnivore.omnivore.DatastoreKeys import app.omnivore.omnivore.DatastoreRepository @@ -22,6 +24,11 @@ class HomeViewModel @Inject constructor( private var items: List = listOf() private var searchedItems: List = listOf() + // These are used to make sure we handle search result + // responses in the right order + private var searchIdx = 0 + private var receivedIdx = 0 + // Live Data val searchTextLiveData = MutableLiveData("") val itemsLiveData = MutableLiveData>(listOf()) @@ -42,6 +49,8 @@ class HomeViewModel @Inject constructor( fun load(clearPreviousSearch: Boolean = false) { viewModelScope.launch { + val thisSearchIdx = searchIdx + searchIdx += 1 val authToken = getAuthToken() val apolloClient = ApolloClient.Builder() @@ -57,7 +66,18 @@ class HomeViewModel @Inject constructor( ) ).execute() + // Search results aren't guaranteed to return in order so this + // will discard old results that are returned while a user is typing. + // For example if a user types 'Canucks', often the search results + // for 'C' are returned after 'Canucks' because it takes the backend + // much longer to compute. + if (thisSearchIdx in 1..receivedIdx) { + Log.d("loggo", "early return from load function") + return@launch + } + cursor = response.data?.search?.onSearchSuccess?.pageInfo?.endCursor + receivedIdx = thisSearchIdx val itemList = response.data?.search?.onSearchSuccess?.edges ?: listOf() val newItems = itemList.map {