#26 Search problem - some results disappear as typing advances - debounce and search with a copy of the fileReader

This commit is contained in:
Sean Mac Gillicuddy 2020-05-29 16:38:02 +01:00
parent fda37a3e92
commit df1ffd0354
4 changed files with 20 additions and 9 deletions

View File

@ -70,6 +70,8 @@ class ZimReaderContainer @Inject constructor(
zimFileReader?.load(url) zimFileReader?.load(url)
) )
fun copyReader(): ZimFileReader? = zimFile?.let(zimFileReaderFactory::create)
val zimFile get() = zimFileReader?.zimFile val zimFile get() = zimFileReader?.zimFile
val zimCanonicalPath get() = zimFileReader?.zimFile?.canonicalPath val zimCanonicalPath get() = zimFileReader?.zimFile?.canonicalPath

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.core.search.viewmodel package org.kiwix.kiwixmobile.core.search.viewmodel
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem.ZimSearchResultListItem import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem.ZimSearchResultListItem
@ -33,22 +34,26 @@ class ZimSearchResultGenerator @Inject constructor(
private val zimReaderContainer: ZimReaderContainer private val zimReaderContainer: ZimReaderContainer
) : SearchResultGenerator { ) : SearchResultGenerator {
override fun generateSearchResults(searchTerm: String) = override fun generateSearchResults(searchTerm: String) =
if (searchTerm.isNotEmpty()) readResultsFromZim(searchTerm) if (searchTerm.isNotEmpty()) readResultsFromZim(searchTerm, zimReaderContainer.copyReader())
else emptyList() else emptyList()
private fun readResultsFromZim(it: String) = private fun readResultsFromZim(
it: String,
reader: ZimFileReader?
) =
if (sharedPreferenceUtil.prefFullTextSearch) if (sharedPreferenceUtil.prefFullTextSearch)
zimReaderContainer.search(it, 200).run { fullTextResults() } zimReaderContainer.search(it, 200).run { fullTextResults() }
else else
zimReaderContainer.searchSuggestions(it, 200).run { suggestionResults() } reader?.searchSuggestions(it, 200).run { suggestionResults(reader) }
private fun fullTextResults() = generateSequence { private fun fullTextResults() = generateSequence {
zimReaderContainer.getNextResult()?.title?.let(::ZimSearchResultListItem) zimReaderContainer.getNextResult()?.title?.let(::ZimSearchResultListItem)
}.filter { it.value.isNotBlank() } }.filter { it.value.isNotBlank() }
.toList() .toList()
private fun suggestionResults() = generateSequence { private fun suggestionResults(reader: ZimFileReader?) = generateSequence {
zimReaderContainer.getNextSuggestion()?.let { ZimSearchResultListItem(it.title) } reader?.getNextSuggestion()?.let { ZimSearchResultListItem(it.title) }
}.distinct() }
.distinct()
.toList() .toList()
} }

View File

@ -55,8 +55,11 @@ import org.kiwix.kiwixmobile.core.search.viewmodel.effects.SearchIntentProcessin
import org.kiwix.kiwixmobile.core.search.viewmodel.effects.ShowDeleteSearchDialog import org.kiwix.kiwixmobile.core.search.viewmodel.effects.ShowDeleteSearchDialog
import org.kiwix.kiwixmobile.core.search.viewmodel.effects.ShowToast import org.kiwix.kiwixmobile.core.search.viewmodel.effects.ShowToast
import org.kiwix.kiwixmobile.core.search.viewmodel.effects.StartSpeechInput import org.kiwix.kiwixmobile.core.search.viewmodel.effects.StartSpeechInput
import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
private const val DEBOUNCE_MS = 500L
class SearchViewModel @Inject constructor( class SearchViewModel @Inject constructor(
private val recentSearchDao: NewRecentSearchDao, private val recentSearchDao: NewRecentSearchDao,
private val zimReaderContainer: ZimReaderContainer, private val zimReaderContainer: ZimReaderContainer,
@ -148,6 +151,7 @@ class SearchViewModel @Inject constructor(
private fun searchResultsFromZimReader() = filter private fun searchResultsFromZimReader() = filter
.distinctUntilChanged() .distinctUntilChanged()
.debounce(DEBOUNCE_MS, TimeUnit.MILLISECONDS)
.switchMap(::searchResults) .switchMap(::searchResults)
private fun searchResults(it: String) = Flowable.fromCallable { private fun searchResults(it: String) = Flowable.fromCallable {

View File

@ -46,8 +46,8 @@ import org.kiwix.kiwixmobile.core.search.viewmodel.Action.Filter
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemClick import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemClick
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemLongClick import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemLongClick
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ReceivedPromptForSpeechInput import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ReceivedPromptForSpeechInput
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.StartSpeechInputFailed
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ScreenWasStartedFrom import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ScreenWasStartedFrom
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.StartSpeechInputFailed
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromTabView import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromTabView
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromWebView import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromWebView
import org.kiwix.kiwixmobile.core.search.viewmodel.State.NoResults import org.kiwix.kiwixmobile.core.search.viewmodel.State.NoResults
@ -166,7 +166,6 @@ internal class SearchViewModelTest {
viewModel.state.test() viewModel.state.test()
.also { testScheduler.advanceTimeBy(100, MILLISECONDS) } .also { testScheduler.advanceTimeBy(100, MILLISECONDS) }
.assertValueHistory( .assertValueHistory(
NoResults("", FromWebView),
Results(searchString, listOf(item), FromWebView) Results(searchString, listOf(item), FromWebView)
) )
} }
@ -188,7 +187,7 @@ internal class SearchViewModelTest {
) )
viewModel.state.test() viewModel.state.test()
.also { testScheduler.advanceTimeBy(100, MILLISECONDS) } .also { testScheduler.advanceTimeBy(100, MILLISECONDS) }
.assertValueHistory(NoResults("", FromWebView), Results("b", listOf(item), FromWebView)) .assertValueHistory(Results("b", listOf(item), FromWebView))
} }
@Test @Test
@ -315,5 +314,6 @@ internal class SearchViewModelTest {
viewModel.actions.offer(Filter(searchTerm)) viewModel.actions.offer(Filter(searchTerm))
recentsFromDb.offer(databaseResults) recentsFromDb.offer(databaseResults)
viewModel.actions.offer(ScreenWasStartedFrom(searchOrigin)) viewModel.actions.offer(ScreenWasStartedFrom(searchOrigin))
testScheduler.advanceTimeBy(500, MILLISECONDS)
} }
} }