mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
#3810 Convert DepictedImagesFragment to use Pagination - rename base classes to better reflect usage
This commit is contained in:
parent
181a63a233
commit
310c29c2bd
25 changed files with 104 additions and 103 deletions
|
|
@ -1,12 +1,12 @@
|
|||
package fr.free.nrw.commons.depictions.Media
|
||||
|
||||
import fr.free.nrw.commons.Media
|
||||
import fr.free.nrw.commons.explore.SearchFragmentContract
|
||||
import fr.free.nrw.commons.explore.PagingContract
|
||||
|
||||
/**
|
||||
* Contract with which DepictedImagesFragment and its presenter will talk to each other
|
||||
*/
|
||||
interface DepictedImagesContract {
|
||||
interface View : SearchFragmentContract.View<Media>
|
||||
interface Presenter : SearchFragmentContract.Presenter<Media>
|
||||
interface View : PagingContract.View<Media>
|
||||
interface Presenter : PagingContract.Presenter<Media>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ class DepictedImagesFragment : PageableMediaFragment(), DepictedImagesContract.V
|
|||
@Inject
|
||||
lateinit var presenter: DepictedImagesContract.Presenter
|
||||
|
||||
override val injectedPresenter: DepictedImagesContract.Presenter
|
||||
override val injectedPresenter
|
||||
get() = presenter
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
injectedPresenter.onQueryUpdated(arguments!!.getString("entityId")!!)
|
||||
onQueryUpdated(arguments!!.getString("entityId")!!)
|
||||
}
|
||||
|
||||
override fun onItemClicked(position: Int) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package fr.free.nrw.commons.depictions.Media
|
|||
|
||||
import fr.free.nrw.commons.Media
|
||||
import fr.free.nrw.commons.di.CommonsApplicationModule
|
||||
import fr.free.nrw.commons.explore.BaseSearchPresenter
|
||||
import fr.free.nrw.commons.explore.BasePagingPresenter
|
||||
import io.reactivex.Scheduler
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
|
@ -13,5 +13,5 @@ import javax.inject.Named
|
|||
class DepictedImagesPresenter @Inject constructor(
|
||||
@Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler,
|
||||
dataSourceFactory: PageableDepictedMediaDataSource
|
||||
) : BaseSearchPresenter<Media>(mainThreadScheduler, dataSourceFactory),
|
||||
) : BasePagingPresenter<Media>(mainThreadScheduler, dataSourceFactory),
|
||||
DepictedImagesContract.Presenter
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package fr.free.nrw.commons.depictions.Media
|
|||
|
||||
import fr.free.nrw.commons.Media
|
||||
import fr.free.nrw.commons.explore.LiveDataConverter
|
||||
import fr.free.nrw.commons.explore.PageableDataSource
|
||||
import fr.free.nrw.commons.explore.PageableBaseDataSource
|
||||
import fr.free.nrw.commons.explore.depictions.LoadFunction
|
||||
import fr.free.nrw.commons.media.MediaClient
|
||||
import javax.inject.Inject
|
||||
|
|
@ -10,7 +10,7 @@ import javax.inject.Inject
|
|||
class PageableDepictedMediaDataSource @Inject constructor(
|
||||
liveDataConverter: LiveDataConverter,
|
||||
private val mediaClient: MediaClient
|
||||
) : PageableDataSource<Media>(liveDataConverter) {
|
||||
) : PageableBaseDataSource<Media>(liveDataConverter) {
|
||||
override val loadFunction: LoadFunction<Media> = { loadSize: Int, startPosition: Int ->
|
||||
mediaClient.fetchImagesForDepictedItem(query, loadSize, startPosition).blockingGet()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ import fr.free.nrw.commons.utils.ViewUtil
|
|||
import kotlinx.android.synthetic.main.fragment_search_paginated.*
|
||||
|
||||
|
||||
abstract class BaseSearchFragment<T> : CommonsDaggerSupportFragment(),
|
||||
SearchFragmentContract.View<T> {
|
||||
abstract class BasePagingFragment<T> : CommonsDaggerSupportFragment(),
|
||||
PagingContract.View<T> {
|
||||
|
||||
abstract val pagedListAdapter: PagedListAdapter<T, *>
|
||||
abstract val injectedPresenter: SearchFragmentContract.Presenter<T>
|
||||
abstract val injectedPresenter: PagingContract.Presenter<T>
|
||||
abstract val errorTextId: Int
|
||||
private val loadingAdapter by lazy { FooterAdapter { injectedPresenter.retryFailedRequest() } }
|
||||
private val mergeAdapter by lazy { MergeAdapter(pagedListAdapter, loadingAdapter) }
|
||||
|
|
@ -47,11 +47,12 @@ abstract class BaseSearchFragment<T> : CommonsDaggerSupportFragment(),
|
|||
)
|
||||
}
|
||||
|
||||
override fun observeSearchResults(searchResults: LiveData<PagedList<T>>) {
|
||||
override fun observePagingResults(searchResults: LiveData<PagedList<T>>) {
|
||||
this.searchResults?.removeObservers(viewLifecycleOwner)
|
||||
this.searchResults = searchResults
|
||||
searchResults.observe(viewLifecycleOwner, Observer {
|
||||
pagedListAdapter.submitList(it) })
|
||||
pagedListAdapter.submitList(it)
|
||||
})
|
||||
}
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
|
|
@ -85,7 +86,7 @@ abstract class BaseSearchFragment<T> : CommonsDaggerSupportFragment(),
|
|||
contentNotFound.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
abstract fun getEmptyText(query: String):String
|
||||
abstract fun getEmptyText(query: String): String
|
||||
|
||||
override fun hideEmptyText() {
|
||||
contentNotFound.visibility = View.GONE
|
||||
|
|
@ -7,25 +7,25 @@ import io.reactivex.disposables.CompositeDisposable
|
|||
import timber.log.Timber
|
||||
|
||||
|
||||
abstract class BaseSearchPresenter<T>(
|
||||
abstract class BasePagingPresenter<T>(
|
||||
val mainThreadScheduler: Scheduler,
|
||||
val pageableDataSource: PageableDataSource<T>
|
||||
) : SearchFragmentContract.Presenter<T> {
|
||||
val pageableBaseDataSource: PageableBaseDataSource<T>
|
||||
) : PagingContract.Presenter<T> {
|
||||
|
||||
private val DUMMY: SearchFragmentContract.View<T> = proxy()
|
||||
private var view: SearchFragmentContract.View<T> = DUMMY
|
||||
private val DUMMY: PagingContract.View<T> = proxy()
|
||||
private var view: PagingContract.View<T> = DUMMY
|
||||
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
override val listFooterData = MutableLiveData<List<FooterItem>>().apply { value = emptyList() }
|
||||
|
||||
override fun onAttachView(view: SearchFragmentContract.View<T>) {
|
||||
override fun onAttachView(view: PagingContract.View<T>) {
|
||||
this.view = view
|
||||
compositeDisposable.addAll(
|
||||
pageableDataSource.searchResults.subscribe(view::observeSearchResults),
|
||||
pageableDataSource.loadingStates
|
||||
pageableBaseDataSource.pagingResults.subscribe(view::observePagingResults),
|
||||
pageableBaseDataSource.loadingStates
|
||||
.observeOn(mainThreadScheduler)
|
||||
.subscribe(::onLoadingState, Timber::e),
|
||||
pageableDataSource.noItemsLoadedQueries.subscribe(view::showEmptyText)
|
||||
pageableBaseDataSource.noItemsLoadedQueries.subscribe(view::showEmptyText)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ abstract class BaseSearchPresenter<T>(
|
|||
}
|
||||
|
||||
override fun retryFailedRequest() {
|
||||
pageableDataSource.retryFailedRequest()
|
||||
pageableBaseDataSource.retryFailedRequest()
|
||||
}
|
||||
|
||||
override fun onDetachView() {
|
||||
|
|
@ -59,7 +59,7 @@ abstract class BaseSearchPresenter<T>(
|
|||
}
|
||||
|
||||
override fun onQueryUpdated(query: String) {
|
||||
pageableDataSource.onQueryUpdated(query)
|
||||
pageableBaseDataSource.onQueryUpdated(query)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,10 +4,10 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.paging.PagedList
|
||||
import fr.free.nrw.commons.BasePresenter
|
||||
|
||||
interface SearchFragmentContract {
|
||||
interface PagingContract {
|
||||
interface View<T> {
|
||||
fun showSnackbar()
|
||||
fun observeSearchResults(searchResults: LiveData<PagedList<T>>)
|
||||
fun observePagingResults(searchResults: LiveData<PagedList<T>>)
|
||||
fun showInitialLoadInProgress()
|
||||
fun hideInitialLoadProgress()
|
||||
fun showEmptyText(query: String)
|
||||
|
|
@ -14,25 +14,25 @@ import javax.inject.Inject
|
|||
private const val PAGE_SIZE = 50
|
||||
private const val INITIAL_LOAD_SIZE = 50
|
||||
|
||||
abstract class PageableDataSource<T>(private val liveDataConverter: LiveDataConverter) {
|
||||
abstract class PageableBaseDataSource<T>(private val liveDataConverter: LiveDataConverter) {
|
||||
|
||||
lateinit var query: String
|
||||
private val dataSourceFactoryFactory: () -> SearchDataSourceFactory<T> = {
|
||||
private val dataSourceFactoryFactory: () -> PagingDataSourceFactory<T> = {
|
||||
dataSourceFactory(_loadingStates, loadFunction)
|
||||
}
|
||||
private val _loadingStates = PublishProcessor.create<LoadingState>()
|
||||
val loadingStates: Flowable<LoadingState> = _loadingStates
|
||||
private val _searchResults = PublishProcessor.create<LiveData<PagedList<T>>>()
|
||||
val searchResults: Flowable<LiveData<PagedList<T>>> = _searchResults
|
||||
private val _pagingResults = PublishProcessor.create<LiveData<PagedList<T>>>()
|
||||
val pagingResults: Flowable<LiveData<PagedList<T>>> = _pagingResults
|
||||
private val _noItemsLoadedEvent = PublishProcessor.create<String>()
|
||||
val noItemsLoadedQueries: Flowable<String> = _noItemsLoadedEvent
|
||||
private var currentFactory: SearchDataSourceFactory<T>? = null
|
||||
private var currentFactory: PagingDataSourceFactory<T>? = null
|
||||
|
||||
abstract val loadFunction: LoadFunction<T>
|
||||
|
||||
fun onQueryUpdated(query: String) {
|
||||
this.query = query
|
||||
_searchResults.offer(
|
||||
_pagingResults.offer(
|
||||
liveDataConverter.convert(dataSourceFactoryFactory().also { currentFactory = it }) {
|
||||
_noItemsLoadedEvent.offer(query)
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ abstract class PageableDataSource<T>(private val liveDataConverter: LiveDataConv
|
|||
|
||||
class LiveDataConverter @Inject constructor() {
|
||||
fun <T> convert(
|
||||
dataSourceFactory: SearchDataSourceFactory<T>,
|
||||
dataSourceFactory: PagingDataSourceFactory<T>,
|
||||
zeroItemsLoadedFunction: () -> Unit
|
||||
): LiveData<PagedList<T>> {
|
||||
return dataSourceFactory.toLiveData(
|
||||
|
|
@ -65,7 +65,7 @@ class LiveDataConverter @Inject constructor() {
|
|||
|
||||
}
|
||||
|
||||
abstract class SearchDataSourceFactory<T>(val loadingStates: LoadingStates) :
|
||||
abstract class PagingDataSourceFactory<T>(val loadingStates: LoadingStates) :
|
||||
DataSource.Factory<Int, T>() {
|
||||
private var currentDataSource: SearchDataSource<T>? = null
|
||||
abstract val loadFunction: LoadFunction<T>
|
||||
|
|
@ -80,7 +80,7 @@ abstract class SearchDataSourceFactory<T>(val loadingStates: LoadingStates) :
|
|||
}
|
||||
|
||||
fun <T> dataSourceFactory(loadingStates: LoadingStates, loadFunction: LoadFunction<T>) =
|
||||
object : SearchDataSourceFactory<T>(loadingStates) {
|
||||
object : PagingDataSourceFactory<T>(loadingStates) {
|
||||
override val loadFunction: LoadFunction<T> = loadFunction
|
||||
}
|
||||
|
||||
|
|
@ -10,5 +10,5 @@ import javax.inject.Named
|
|||
class SearchCategoriesFragmentPresenter @Inject constructor(
|
||||
@Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler,
|
||||
dataSourceFactory: PageableCategoriesDataSource
|
||||
) : BaseSearchPresenter<String>(mainThreadScheduler, dataSourceFactory),
|
||||
) : BasePagingPresenter<String>(mainThreadScheduler, dataSourceFactory),
|
||||
SearchCategoriesFragmentContract.Presenter
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ package fr.free.nrw.commons.explore.categories
|
|||
|
||||
import fr.free.nrw.commons.category.CategoryClient
|
||||
import fr.free.nrw.commons.explore.LiveDataConverter
|
||||
import fr.free.nrw.commons.explore.PageableDataSource
|
||||
import fr.free.nrw.commons.explore.PageableBaseDataSource
|
||||
import javax.inject.Inject
|
||||
|
||||
class PageableCategoriesDataSource @Inject constructor(
|
||||
liveDataConverter: LiveDataConverter,
|
||||
val categoryClient: CategoryClient
|
||||
) : PageableDataSource<String>(liveDataConverter) {
|
||||
) : PageableBaseDataSource<String>(liveDataConverter) {
|
||||
|
||||
override val loadFunction = { loadSize: Int, startPosition: Int ->
|
||||
categoryClient.searchCategories(query, loadSize, startPosition).blockingFirst()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package fr.free.nrw.commons.explore.categories
|
||||
|
||||
import fr.free.nrw.commons.explore.SearchFragmentContract
|
||||
import fr.free.nrw.commons.explore.PagingContract
|
||||
|
||||
interface SearchCategoriesFragmentContract {
|
||||
interface View : SearchFragmentContract.View<String>
|
||||
interface Presenter : SearchFragmentContract.Presenter<String>
|
||||
interface View : PagingContract.View<String>
|
||||
interface Presenter : PagingContract.Presenter<String>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,20 +2,20 @@ package fr.free.nrw.commons.explore.categories
|
|||
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.category.CategoryDetailsActivity
|
||||
import fr.free.nrw.commons.explore.BaseSearchFragment
|
||||
import fr.free.nrw.commons.explore.SearchFragmentContract
|
||||
import fr.free.nrw.commons.explore.BasePagingFragment
|
||||
import fr.free.nrw.commons.explore.PagingContract
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Displays the category search screen.
|
||||
*/
|
||||
class SearchCategoryFragment : BaseSearchFragment<String>() {
|
||||
class SearchCategoryFragment : BasePagingFragment<String>() {
|
||||
@Inject
|
||||
lateinit var presenter: SearchCategoriesFragmentContract.Presenter
|
||||
|
||||
override val errorTextId: Int = R.string.error_loading_categories
|
||||
|
||||
override val injectedPresenter: SearchFragmentContract.Presenter<String>
|
||||
override val injectedPresenter
|
||||
get() = presenter
|
||||
|
||||
override val pagedListAdapter by lazy {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package fr.free.nrw.commons.explore.depictions
|
|||
|
||||
import fr.free.nrw.commons.explore.LiveDataConverter
|
||||
import fr.free.nrw.commons.explore.LoadingState
|
||||
import fr.free.nrw.commons.explore.PageableDataSource
|
||||
import fr.free.nrw.commons.explore.PageableBaseDataSource
|
||||
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
|
||||
import io.reactivex.processors.PublishProcessor
|
||||
import javax.inject.Inject
|
||||
|
|
@ -13,7 +13,7 @@ typealias LoadingStates = PublishProcessor<LoadingState>
|
|||
class PageableDepictionsDataSource @Inject constructor(
|
||||
liveDataConverter: LiveDataConverter,
|
||||
val depictsClient: DepictsClient
|
||||
) : PageableDataSource<DepictedItem>(liveDataConverter) {
|
||||
) : PageableBaseDataSource<DepictedItem>(liveDataConverter) {
|
||||
|
||||
override val loadFunction = { loadSize: Int, startPosition: Int ->
|
||||
depictsClient.searchForDepictions(query, loadSize, startPosition).blockingGet()
|
||||
|
|
|
|||
|
|
@ -2,21 +2,21 @@ package fr.free.nrw.commons.explore.depictions
|
|||
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.depictions.WikidataItemDetailsActivity
|
||||
import fr.free.nrw.commons.explore.BaseSearchFragment
|
||||
import fr.free.nrw.commons.explore.BasePagingFragment
|
||||
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Display depictions in search fragment
|
||||
*/
|
||||
class SearchDepictionsFragment : BaseSearchFragment<DepictedItem>(),
|
||||
class SearchDepictionsFragment : BasePagingFragment<DepictedItem>(),
|
||||
SearchDepictionsFragmentContract.View {
|
||||
@Inject
|
||||
lateinit var presenter: SearchDepictionsFragmentContract.Presenter
|
||||
|
||||
override val errorTextId: Int = R.string.error_loading_depictions
|
||||
|
||||
override val injectedPresenter: SearchDepictionsFragmentContract.Presenter
|
||||
override val injectedPresenter
|
||||
get() = presenter
|
||||
|
||||
override val pagedListAdapter by lazy {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
package fr.free.nrw.commons.explore.depictions
|
||||
|
||||
import fr.free.nrw.commons.explore.SearchFragmentContract
|
||||
import fr.free.nrw.commons.explore.PagingContract
|
||||
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
|
||||
|
||||
/**
|
||||
* The contract with with SearchDepictionsFragment and its presenter would talk to each other
|
||||
*/
|
||||
interface SearchDepictionsFragmentContract {
|
||||
interface View : SearchFragmentContract.View<DepictedItem>
|
||||
interface Presenter : SearchFragmentContract.Presenter<DepictedItem>
|
||||
interface View : PagingContract.View<DepictedItem>
|
||||
interface Presenter : PagingContract.Presenter<DepictedItem>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package fr.free.nrw.commons.explore.depictions
|
||||
|
||||
import fr.free.nrw.commons.di.CommonsApplicationModule
|
||||
import fr.free.nrw.commons.explore.BaseSearchPresenter
|
||||
import fr.free.nrw.commons.explore.BasePagingPresenter
|
||||
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
|
||||
import io.reactivex.Scheduler
|
||||
import javax.inject.Inject
|
||||
|
|
@ -13,5 +13,5 @@ import javax.inject.Named
|
|||
class SearchDepictionsFragmentPresenter @Inject constructor(
|
||||
@Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler,
|
||||
dataSourceFactory: PageableDepictionsDataSource
|
||||
) : BaseSearchPresenter<DepictedItem>(mainThreadScheduler, dataSourceFactory),
|
||||
) : BasePagingPresenter<DepictedItem>(mainThreadScheduler, dataSourceFactory),
|
||||
SearchDepictionsFragmentContract.Presenter
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package fr.free.nrw.commons.explore.media
|
|||
|
||||
import fr.free.nrw.commons.Media
|
||||
import fr.free.nrw.commons.explore.LiveDataConverter
|
||||
import fr.free.nrw.commons.explore.PageableDataSource
|
||||
import fr.free.nrw.commons.explore.PageableBaseDataSource
|
||||
import fr.free.nrw.commons.explore.depictions.LoadFunction
|
||||
import fr.free.nrw.commons.media.MediaClient
|
||||
import javax.inject.Inject
|
||||
|
|
@ -10,7 +10,7 @@ import javax.inject.Inject
|
|||
class PageableMediaDataSource @Inject constructor(
|
||||
liveDataConverter: LiveDataConverter,
|
||||
private val mediaClient: MediaClient
|
||||
) : PageableDataSource<Media>(liveDataConverter) {
|
||||
) : PageableBaseDataSource<Media>(liveDataConverter) {
|
||||
override val loadFunction: LoadFunction<Media> = { loadSize: Int, startPosition: Int ->
|
||||
mediaClient.getMediaListFromSearch(query, loadSize, startPosition).blockingGet()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ import android.os.Bundle
|
|||
import android.view.View
|
||||
import fr.free.nrw.commons.Media
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.explore.BaseSearchFragment
|
||||
import fr.free.nrw.commons.explore.BasePagingFragment
|
||||
import kotlinx.android.synthetic.main.fragment_search_paginated.*
|
||||
|
||||
|
||||
abstract class PageableMediaFragment : BaseSearchFragment<Media>() {
|
||||
abstract class PageableMediaFragment : BasePagingFragment<Media>() {
|
||||
override val pagedListAdapter by lazy { PagedMediaAdapter(::onItemClicked) }
|
||||
|
||||
override val errorTextId: Int = R.string.error_loading_images
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class SearchMediaFragment : PageableMediaFragment(), SearchMediaFragmentContract
|
|||
@Inject
|
||||
lateinit var presenter: SearchMediaFragmentContract.Presenter
|
||||
|
||||
override val injectedPresenter: SearchMediaFragmentContract.Presenter
|
||||
override val injectedPresenter
|
||||
get() = presenter
|
||||
|
||||
override fun onItemClicked(position: Int) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package fr.free.nrw.commons.explore.media
|
||||
|
||||
import fr.free.nrw.commons.Media
|
||||
import fr.free.nrw.commons.explore.SearchFragmentContract
|
||||
import fr.free.nrw.commons.explore.PagingContract
|
||||
|
||||
|
||||
interface SearchMediaFragmentContract {
|
||||
interface View : SearchFragmentContract.View<Media>
|
||||
interface Presenter : SearchFragmentContract.Presenter<Media>
|
||||
interface View : PagingContract.View<Media>
|
||||
interface Presenter : PagingContract.Presenter<Media>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package fr.free.nrw.commons.explore.media
|
|||
|
||||
import fr.free.nrw.commons.Media
|
||||
import fr.free.nrw.commons.di.CommonsApplicationModule
|
||||
import fr.free.nrw.commons.explore.BaseSearchPresenter
|
||||
import fr.free.nrw.commons.explore.BasePagingPresenter
|
||||
import io.reactivex.Scheduler
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
|
@ -10,5 +10,5 @@ import javax.inject.Named
|
|||
class SearchMediaFragmentPresenter @Inject constructor(
|
||||
@Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler,
|
||||
dataSourceFactory: PageableMediaDataSource
|
||||
) : BaseSearchPresenter<Media>(mainThreadScheduler, dataSourceFactory),
|
||||
) : BasePagingPresenter<Media>(mainThreadScheduler, dataSourceFactory),
|
||||
SearchMediaFragmentContract.Presenter
|
||||
|
|
|
|||
|
|
@ -15,21 +15,21 @@ import org.junit.Test
|
|||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
class BaseSearchPresenterTest {
|
||||
class BasePagingPresenterTest {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||
|
||||
@Mock
|
||||
internal lateinit var view: SearchFragmentContract.View<String>
|
||||
internal lateinit var view: PagingContract.View<String>
|
||||
|
||||
private lateinit var baseSearchPresenter: BaseSearchPresenter<String>
|
||||
private lateinit var basePagingPresenter: BasePagingPresenter<String>
|
||||
|
||||
private lateinit var testScheduler: TestScheduler
|
||||
|
||||
@Mock
|
||||
private lateinit var pageableDataSource: PageableDataSource<String>
|
||||
private lateinit var pageableBaseDataSource: PageableBaseDataSource<String>
|
||||
|
||||
private var loadingStates: PublishProcessor<LoadingState> = PublishProcessor.create()
|
||||
|
||||
|
|
@ -42,34 +42,34 @@ class BaseSearchPresenterTest {
|
|||
@Throws(Exception::class)
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
whenever(pageableDataSource.searchResults).thenReturn(searchResults)
|
||||
whenever(pageableDataSource.loadingStates).thenReturn(loadingStates)
|
||||
whenever(pageableDataSource.noItemsLoadedQueries)
|
||||
whenever(pageableBaseDataSource.pagingResults).thenReturn(searchResults)
|
||||
whenever(pageableBaseDataSource.loadingStates).thenReturn(loadingStates)
|
||||
whenever(pageableBaseDataSource.noItemsLoadedQueries)
|
||||
.thenReturn(noItemLoadedQueries)
|
||||
testScheduler = TestScheduler()
|
||||
baseSearchPresenter =
|
||||
object : BaseSearchPresenter<String>(testScheduler, pageableDataSource) {}
|
||||
baseSearchPresenter.onAttachView(view)
|
||||
basePagingPresenter =
|
||||
object : BasePagingPresenter<String>(testScheduler, pageableBaseDataSource) {}
|
||||
basePagingPresenter.onAttachView(view)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `searchResults emission updates the view`() {
|
||||
val pagedListLiveData = mock<LiveData<PagedList<String>>>()
|
||||
searchResults.offer(pagedListLiveData)
|
||||
verify(view).observeSearchResults(pagedListLiveData)
|
||||
verify(view).observePagingResults(pagedListLiveData)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Loading offers a loading list item`() {
|
||||
onLoadingState(LoadingState.Loading)
|
||||
verify(view).hideEmptyText()
|
||||
baseSearchPresenter.listFooterData.test().assertValue(listOf(FooterItem.LoadingItem))
|
||||
basePagingPresenter.listFooterData.test().assertValue(listOf(FooterItem.LoadingItem))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Complete offers an empty list item and hides initial loader`() {
|
||||
onLoadingState(LoadingState.Complete)
|
||||
baseSearchPresenter.listFooterData.test()
|
||||
basePagingPresenter.listFooterData.test()
|
||||
.assertValue(emptyList())
|
||||
verify(view).hideInitialLoadProgress()
|
||||
}
|
||||
|
|
@ -83,11 +83,11 @@ class BaseSearchPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `Error offers a refresh list item, hides initial loader and shows error with a set text`() {
|
||||
baseSearchPresenter.onQueryUpdated("test")
|
||||
basePagingPresenter.onQueryUpdated("test")
|
||||
onLoadingState(LoadingState.Error)
|
||||
verify(view).showSnackbar()
|
||||
verify(view).hideInitialLoadProgress()
|
||||
baseSearchPresenter.listFooterData.test().assertValue(listOf(FooterItem.RefreshItem))
|
||||
basePagingPresenter.listFooterData.test().assertValue(listOf(FooterItem.RefreshItem))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -98,21 +98,21 @@ class BaseSearchPresenterTest {
|
|||
|
||||
@Test
|
||||
fun `retryFailedRequest calls retry`() {
|
||||
baseSearchPresenter.retryFailedRequest()
|
||||
verify(pageableDataSource).retryFailedRequest()
|
||||
basePagingPresenter.retryFailedRequest()
|
||||
verify(pageableBaseDataSource).retryFailedRequest()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `onDetachView stops subscriptions`() {
|
||||
baseSearchPresenter.onDetachView()
|
||||
basePagingPresenter.onDetachView()
|
||||
onLoadingState(LoadingState.Loading)
|
||||
baseSearchPresenter.listFooterData.test().assertValue(emptyList())
|
||||
basePagingPresenter.listFooterData.test().assertValue(emptyList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `onQueryUpdated updates dataSourceFactory`() {
|
||||
baseSearchPresenter.onQueryUpdated("test")
|
||||
verify(pageableDataSource).onQueryUpdated("test")
|
||||
basePagingPresenter.onQueryUpdated("test")
|
||||
verify(pageableBaseDataSource).onQueryUpdated("test")
|
||||
}
|
||||
|
||||
private fun onLoadingState(loadingState: LoadingState) {
|
||||
|
|
@ -10,17 +10,17 @@ import org.junit.Test
|
|||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
class PageableDataSourceTest {
|
||||
class PageableBaseDataSourceTest {
|
||||
|
||||
@Mock
|
||||
private lateinit var liveDataConverter: LiveDataConverter
|
||||
|
||||
private lateinit var pageableDataSource: PageableDataSource<String>
|
||||
private lateinit var pageableBaseDataSource: PageableBaseDataSource<String>
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
pageableDataSource = object: PageableDataSource<String>(liveDataConverter){
|
||||
pageableBaseDataSource = object: PageableBaseDataSource<String>(liveDataConverter){
|
||||
override val loadFunction: LoadFunction<String>
|
||||
get() = mock()
|
||||
|
||||
|
|
@ -30,16 +30,16 @@ class PageableDataSourceTest {
|
|||
@Test
|
||||
fun `onQueryUpdated emits new liveData`() {
|
||||
val (_, liveData) = expectNewLiveData()
|
||||
pageableDataSource.searchResults.test()
|
||||
.also { pageableDataSource.onQueryUpdated("test") }
|
||||
pageableBaseDataSource.pagingResults.test()
|
||||
.also { pageableBaseDataSource.onQueryUpdated("test") }
|
||||
.assertValue(liveData)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `onQueryUpdated invokes livedatconverter with no items emitter`() {
|
||||
val (zeroItemsFuncCaptor, _) = expectNewLiveData()
|
||||
pageableDataSource.onQueryUpdated("test")
|
||||
pageableDataSource.noItemsLoadedQueries.test()
|
||||
pageableBaseDataSource.onQueryUpdated("test")
|
||||
pageableBaseDataSource.noItemsLoadedQueries.test()
|
||||
.also { zeroItemsFuncCaptor.firstValue.invoke() }
|
||||
.assertValue("test")
|
||||
}
|
||||
|
|
@ -49,22 +49,22 @@ class PageableDataSourceTest {
|
|||
* */
|
||||
@Test
|
||||
fun `retryFailedRequest does nothing without a factory`() {
|
||||
pageableDataSource.retryFailedRequest()
|
||||
pageableBaseDataSource.retryFailedRequest()
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Rewrite with Mockk constructor mocks")
|
||||
fun `retryFailedRequest retries with a factory`() {
|
||||
val (_, _, dataSourceFactoryCaptor) = expectNewLiveData()
|
||||
pageableDataSource.onQueryUpdated("test")
|
||||
pageableBaseDataSource.onQueryUpdated("test")
|
||||
val dataSourceFactory = spy(dataSourceFactoryCaptor.firstValue)
|
||||
pageableDataSource.retryFailedRequest()
|
||||
pageableBaseDataSource.retryFailedRequest()
|
||||
verify(dataSourceFactory).retryFailedRequest()
|
||||
}
|
||||
|
||||
private fun expectNewLiveData(): Triple<KArgumentCaptor<() -> Unit>, LiveData<PagedList<String>>, KArgumentCaptor<SearchDataSourceFactory<String>>> {
|
||||
private fun expectNewLiveData(): Triple<KArgumentCaptor<() -> Unit>, LiveData<PagedList<String>>, KArgumentCaptor<PagingDataSourceFactory<String>>> {
|
||||
val captor = argumentCaptor<() -> Unit>()
|
||||
val dataSourceFactoryCaptor = argumentCaptor<SearchDataSourceFactory<String>>()
|
||||
val dataSourceFactoryCaptor = argumentCaptor<PagingDataSourceFactory<String>>()
|
||||
val liveData: LiveData<PagedList<String>> = mock()
|
||||
whenever(liveDataConverter.convert(dataSourceFactoryCaptor.capture(), captor.capture()))
|
||||
.thenReturn(liveData)
|
||||
|
|
@ -14,21 +14,21 @@ import org.mockito.Mock
|
|||
import org.mockito.Mockito
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
class SearchDataSourceFactoryTest {
|
||||
class PagingDataSourceFactoryTest {
|
||||
|
||||
@Mock
|
||||
private lateinit var depictsClient: DepictsClient
|
||||
|
||||
@Mock
|
||||
private lateinit var loadingStates: PublishProcessor<LoadingState>
|
||||
private lateinit var factory: SearchDataSourceFactory<String>
|
||||
private lateinit var factory: PagingDataSourceFactory<String>
|
||||
|
||||
private var function: (Int, Int) -> List<String> = mock()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
factory = object : SearchDataSourceFactory<String>(loadingStates) {
|
||||
factory = object : PagingDataSourceFactory<String>(loadingStates) {
|
||||
override val loadFunction get() = function
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue