Fixed bugs and enhanced search functionality.

* A bug was introduced after enhancing the search functionality to align with the new `java-libkiwix` wrapper. Initially, when searching for any article in the ZIM file, the loading progress bar was not being displayed. This commit resolves this issue.
* While searching within large ZIM files, the application used to freeze momentarily due to fetching data from the `libkiwix` on the UI thread. We have improved this functionality to provide a seamless user experience.
This commit is contained in:
MohitMali 2023-08-10 18:32:20 +05:30
parent 734885a527
commit acf45a0f60
2 changed files with 21 additions and 14 deletions

View File

@ -40,7 +40,9 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.base.BaseActivity import org.kiwix.kiwixmobile.core.base.BaseActivity
import org.kiwix.kiwixmobile.core.base.BaseFragment import org.kiwix.kiwixmobile.core.base.BaseFragment
@ -82,6 +84,7 @@ class SearchFragment : BaseFragment() {
private var searchAdapter: SearchAdapter? = null private var searchAdapter: SearchAdapter? = null
private var isDataLoading = false private var isDataLoading = false
private var searchState: SearchState? = null private var searchState: SearchState? = null
private var renderingJob: Job? = null
override fun inject(baseActivity: BaseActivity) { override fun inject(baseActivity: BaseActivity) {
baseActivity.cachedComponent.inject(this) baseActivity.cachedComponent.inject(this)
@ -200,6 +203,8 @@ class SearchFragment : BaseFragment() {
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
renderingJob?.cancel()
renderingJob = null
searchState = null searchState = null
activity?.intent?.action = null activity?.intent?.action = null
searchView = null searchView = null
@ -258,17 +263,24 @@ class SearchFragment : BaseFragment() {
) )
} }
private suspend fun render(state: SearchState) { private fun render(state: SearchState) {
renderingJob?.cancel()
isDataLoading = false isDataLoading = false
searchState = state searchState = state
searchInTextMenuItem?.isVisible = state.searchOrigin == FromWebView searchInTextMenuItem?.isVisible = state.searchOrigin == FromWebView
searchInTextMenuItem?.isEnabled = state.searchTerm.isNotBlank() searchInTextMenuItem?.isEnabled = state.searchTerm.isNotBlank()
fragmentSearchBinding?.searchLoadingIndicator?.isShowing(state.isLoading) fragmentSearchBinding?.searchLoadingIndicator?.isShowing(true)
val searchResult = state.getVisibleResults(0) renderingJob = CoroutineScope(Dispatchers.Main).launch {
fragmentSearchBinding?.searchNoResults?.isVisible = val searchResult = withContext(Dispatchers.IO) {
searchResult?.isEmpty() == true state.getVisibleResults(0)
searchResult?.let { }
searchAdapter?.items = it
fragmentSearchBinding?.searchLoadingIndicator?.isShowing(false)
searchResult?.let {
fragmentSearchBinding?.searchNoResults?.isVisible = it.isEmpty()
searchAdapter?.items = it
}
} }
} }

View File

@ -26,13 +26,10 @@ data class SearchState(
val recentResults: List<SearchListItem.RecentSearchListItem>, val recentResults: List<SearchListItem.RecentSearchListItem>,
val searchOrigin: SearchOrigin val searchOrigin: SearchOrigin
) { ) {
private var isDataLoading = false fun getVisibleResults(startIndex: Int): List<SearchListItem.RecentSearchListItem>? =
suspend fun getVisibleResults(startIndex: Int): List<SearchListItem.RecentSearchListItem>? =
if (searchTerm.isEmpty()) { if (searchTerm.isEmpty()) {
isDataLoading = false
recentResults recentResults
} else { } else {
isDataLoading = true
searchResultsWithTerm.suggestionSearch?.let { searchResultsWithTerm.suggestionSearch?.let {
val maximumResults = it.estimatedMatches val maximumResults = it.estimatedMatches
val safeEndIndex = val safeEndIndex =
@ -49,15 +46,13 @@ data class SearchState(
* We check this in SearchFragment to avoid unnecessary data loading * We check this in SearchFragment to avoid unnecessary data loading
* while scrolling to the end of the list when there are no items available. * while scrolling to the end of the list when there are no items available.
*/ */
isDataLoading = false
searchResults.ifEmpty { null } searchResults.ifEmpty { null }
} ?: kotlin.run { } ?: kotlin.run {
isDataLoading = false
recentResults recentResults
} }
} }
val isLoading get() = searchTerm != searchResultsWithTerm.searchTerm || isDataLoading val isLoading = searchTerm != searchResultsWithTerm.searchTerm
} }
enum class SearchOrigin { enum class SearchOrigin {