mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
#3822 Convert SubCategoryImagesListFragment to use Pagination - convert subcategories - add continuation support in category client - rely on interfaces for callbacks of PageableMediaFragments
This commit is contained in:
parent
0dad78358d
commit
5b87ed569c
26 changed files with 253 additions and 92 deletions
|
|
@ -142,4 +142,9 @@ public class BookmarksActivity extends NavigationBaseActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestMoreImages() { }
|
public void requestMoreImages() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMediaClicked(int position) {
|
||||||
|
//TODO use with pagination
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ class CategoriesModel @Inject constructor(
|
||||||
else
|
else
|
||||||
categoryClient.searchCategoriesForPrefix(term.toLowerCase(), SEARCH_CATS_LIMIT)
|
categoryClient.searchCategoriesForPrefix(term.toLowerCase(), SEARCH_CATS_LIMIT)
|
||||||
.map { it.sortedWith(StringSortingUtils.sortBySimilarity(term)) }
|
.map { it.sortedWith(StringSortingUtils.sortBySimilarity(term)) }
|
||||||
|
.toObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun categoriesFromDepiction(selectedDepictions: List<DepictedItem>) =
|
private fun categoriesFromDepiction(selectedDepictions: List<DepictedItem>) =
|
||||||
|
|
@ -126,7 +127,7 @@ class CategoriesModel @Inject constructor(
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private fun getTitleCategories(title: String): Observable<List<String>> {
|
private fun getTitleCategories(title: String): Observable<List<String>> {
|
||||||
return categoryClient.searchCategories(title.toLowerCase(), SEARCH_CATS_LIMIT)
|
return categoryClient.searchCategories(title.toLowerCase(), SEARCH_CATS_LIMIT).toObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,22 @@
|
||||||
package fr.free.nrw.commons.category
|
package fr.free.nrw.commons.category
|
||||||
|
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Single
|
||||||
import org.wikipedia.dataclient.mwapi.MwQueryResponse
|
import org.wikipedia.dataclient.mwapi.MwQueryResponse
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
const val CATEGORY_PREFIX = "Category:"
|
const val CATEGORY_PREFIX = "Category:"
|
||||||
|
const val SUB_CATEGORY_CONTINUATION_PREFIX = "sub_category_"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Category Client to handle custom calls to Commons MediaWiki APIs
|
* Category Client to handle custom calls to Commons MediaWiki APIs
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
class CategoryClient @Inject constructor(private val categoryInterface: CategoryInterface) {
|
class CategoryClient @Inject constructor(private val categoryInterface: CategoryInterface) {
|
||||||
|
|
||||||
|
private val continuationStore: MutableMap<String, Map<String, String>?> = mutableMapOf()
|
||||||
|
private val continuationExists: MutableMap<String, Boolean> = mutableMapOf()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for categories containing the specified string.
|
* Searches for categories containing the specified string.
|
||||||
*
|
*
|
||||||
|
|
@ -21,8 +27,10 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun searchCategories(filter: String?, itemLimit: Int, offset: Int = 0):
|
fun searchCategories(filter: String?, itemLimit: Int, offset: Int = 0):
|
||||||
Observable<List<String>> {
|
Single<List<String>> {
|
||||||
return responseToCategoryName(categoryInterface.searchCategories(filter, itemLimit, offset))
|
return responseToCategoryName(
|
||||||
|
categoryInterface.searchCategories(filter, itemLimit, offset)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -35,7 +43,7 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun searchCategoriesForPrefix(prefix: String?, itemLimit: Int, offset: Int = 0):
|
fun searchCategoriesForPrefix(prefix: String?, itemLimit: Int, offset: Int = 0):
|
||||||
Observable<List<String>> {
|
Single<List<String>> {
|
||||||
return responseToCategoryName(
|
return responseToCategoryName(
|
||||||
categoryInterface.searchCategoriesForPrefix(prefix, itemLimit, offset)
|
categoryInterface.searchCategoriesForPrefix(prefix, itemLimit, offset)
|
||||||
)
|
)
|
||||||
|
|
@ -48,8 +56,19 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
||||||
* @param categoryName Category name as defined on commons
|
* @param categoryName Category name as defined on commons
|
||||||
* @return Observable emitting the categories returned. If our search yielded "Category:Test", "Test" is emitted.
|
* @return Observable emitting the categories returned. If our search yielded "Category:Test", "Test" is emitted.
|
||||||
*/
|
*/
|
||||||
fun getSubCategoryList(categoryName: String?): Observable<List<String>> {
|
fun getSubCategoryList(categoryName: String?): Single<List<String>> {
|
||||||
return responseToCategoryName(categoryInterface.getSubCategoryList(categoryName))
|
val key = "$SUB_CATEGORY_CONTINUATION_PREFIX$categoryName"
|
||||||
|
return if (hasMorePagesFor(key)) {
|
||||||
|
responseToCategoryName(
|
||||||
|
categoryInterface.getSubCategoryList(
|
||||||
|
categoryName,
|
||||||
|
continuationStore[key] ?: emptyMap()
|
||||||
|
),
|
||||||
|
key
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Single.just(emptyList())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -59,7 +78,7 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
||||||
* @param categoryName Category name as defined on commons
|
* @param categoryName Category name as defined on commons
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun getParentCategoryList(categoryName: String?): Observable<List<String>> {
|
fun getParentCategoryList(categoryName: String?): Single<List<String>> {
|
||||||
return responseToCategoryName(categoryInterface.getParentCategoryList(categoryName))
|
return responseToCategoryName(categoryInterface.getParentCategoryList(categoryName))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,12 +88,30 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category
|
||||||
* @param responseObservable The query response observable
|
* @param responseObservable The query response observable
|
||||||
* @return Observable emitting the categories returned. If our search yielded "Category:Test", "Test" is emitted.
|
* @return Observable emitting the categories returned. If our search yielded "Category:Test", "Test" is emitted.
|
||||||
*/
|
*/
|
||||||
private fun responseToCategoryName(responseObservable: Observable<MwQueryResponse>): Observable<List<String>> {
|
private fun responseToCategoryName(
|
||||||
|
responseObservable: Single<MwQueryResponse>,
|
||||||
|
key: String? = null
|
||||||
|
): Single<List<String>> {
|
||||||
return responseObservable
|
return responseObservable
|
||||||
.map { it.query()?.pages() ?: emptyList() }
|
.map {
|
||||||
|
if (key != null) {
|
||||||
|
continuationExists[key] =
|
||||||
|
it.continuation()?.let { continuation ->
|
||||||
|
continuationStore[key] = continuation
|
||||||
|
true
|
||||||
|
} ?: false
|
||||||
|
}
|
||||||
|
it.query()?.pages() ?: emptyList()
|
||||||
|
}
|
||||||
.map {
|
.map {
|
||||||
it.map { page -> page.title().replace(CATEGORY_PREFIX, "") }
|
it.map { page -> page.title().replace(CATEGORY_PREFIX, "") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun hasMorePagesFor(key: String) = continuationExists[key] ?: true
|
||||||
|
|
||||||
|
fun resetSubCategoryContinuation(category: String) {
|
||||||
|
continuationExists.remove("$SUB_CATEGORY_CONTINUATION_PREFIX$category")
|
||||||
|
continuationStore.remove("$SUB_CATEGORY_CONTINUATION_PREFIX$category")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import fr.free.nrw.commons.R;
|
||||||
import fr.free.nrw.commons.Utils;
|
import fr.free.nrw.commons.Utils;
|
||||||
import fr.free.nrw.commons.explore.ViewPagerAdapter;
|
import fr.free.nrw.commons.explore.ViewPagerAdapter;
|
||||||
import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment;
|
import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment;
|
||||||
|
import fr.free.nrw.commons.explore.categories.sub.SubCategoriesFragment;
|
||||||
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
|
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
|
||||||
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -69,13 +70,12 @@ public class CategoryDetailsActivity extends NavigationBaseActivity
|
||||||
List<Fragment> fragmentList = new ArrayList<>();
|
List<Fragment> fragmentList = new ArrayList<>();
|
||||||
List<String> titleList = new ArrayList<>();
|
List<String> titleList = new ArrayList<>();
|
||||||
categoriesMediaFragment = new CategoriesMediaFragment();
|
categoriesMediaFragment = new CategoriesMediaFragment();
|
||||||
SubCategoryListFragment subCategoryListFragment = new SubCategoryListFragment();
|
SubCategoriesFragment subCategoryListFragment = new SubCategoriesFragment();
|
||||||
SubCategoryListFragment parentCategoryListFragment = new SubCategoryListFragment();
|
SubCategoryListFragment parentCategoryListFragment = new SubCategoryListFragment();
|
||||||
categoryName = getIntent().getStringExtra("categoryName");
|
categoryName = getIntent().getStringExtra("categoryName");
|
||||||
if (getIntent() != null && categoryName != null) {
|
if (getIntent() != null && categoryName != null) {
|
||||||
Bundle arguments = new Bundle();
|
Bundle arguments = new Bundle();
|
||||||
arguments.putString("categoryName", categoryName);
|
arguments.putString("categoryName", categoryName);
|
||||||
arguments.putBoolean("isParentCategory", false);
|
|
||||||
categoriesMediaFragment.setArguments(arguments);
|
categoriesMediaFragment.setArguments(arguments);
|
||||||
subCategoryListFragment.setArguments(arguments);
|
subCategoryListFragment.setArguments(arguments);
|
||||||
Bundle parentCategoryArguments = new Bundle();
|
Bundle parentCategoryArguments = new Bundle();
|
||||||
|
|
|
||||||
|
|
@ -195,4 +195,9 @@ public class CategoryImagesActivity
|
||||||
public void requestMoreImages() {
|
public void requestMoreImages() {
|
||||||
//unneeded
|
//unneeded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMediaClicked(int position) {
|
||||||
|
// this class is unused and will be deleted
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ package fr.free.nrw.commons.category;
|
||||||
public interface CategoryImagesCallback {
|
public interface CategoryImagesCallback {
|
||||||
void viewPagerNotifyDataSetChanged();
|
void viewPagerNotifyDataSetChanged();
|
||||||
void requestMoreImages();
|
void requestMoreImages();
|
||||||
|
void onMediaClicked(int position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
package fr.free.nrw.commons.category;
|
package fr.free.nrw.commons.category;
|
||||||
|
|
||||||
|
import io.reactivex.Single;
|
||||||
|
import java.util.Map;
|
||||||
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
|
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
|
||||||
|
|
||||||
import io.reactivex.Observable;
|
|
||||||
import retrofit2.http.GET;
|
import retrofit2.http.GET;
|
||||||
import retrofit2.http.Query;
|
import retrofit2.http.Query;
|
||||||
|
import retrofit2.http.QueryMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for interacting with Commons category related APIs
|
* Interface for interacting with Commons category related APIs
|
||||||
|
|
@ -20,7 +21,7 @@ public interface CategoryInterface {
|
||||||
*/
|
*/
|
||||||
@GET("w/api.php?action=query&format=json&formatversion=2"
|
@GET("w/api.php?action=query&format=json&formatversion=2"
|
||||||
+ "&generator=search&gsrnamespace=14")
|
+ "&generator=search&gsrnamespace=14")
|
||||||
Observable<MwQueryResponse> searchCategories(@Query("gsrsearch") String filter,
|
Single<MwQueryResponse> searchCategories(@Query("gsrsearch") String filter,
|
||||||
@Query("gsrlimit") int itemLimit, @Query("gsroffset") int offset);
|
@Query("gsrlimit") int itemLimit, @Query("gsroffset") int offset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -32,16 +33,17 @@ public interface CategoryInterface {
|
||||||
*/
|
*/
|
||||||
@GET("w/api.php?action=query&format=json&formatversion=2"
|
@GET("w/api.php?action=query&format=json&formatversion=2"
|
||||||
+ "&generator=allcategories")
|
+ "&generator=allcategories")
|
||||||
Observable<MwQueryResponse> searchCategoriesForPrefix(@Query("gacprefix") String prefix,
|
Single<MwQueryResponse> searchCategoriesForPrefix(@Query("gacprefix") String prefix,
|
||||||
@Query("gaclimit") int itemLimit, @Query("gacoffset") int offset);
|
@Query("gaclimit") int itemLimit, @Query("gacoffset") int offset);
|
||||||
|
|
||||||
@GET("w/api.php?action=query&format=json&formatversion=2"
|
@GET("w/api.php?action=query&format=json&formatversion=2"
|
||||||
+ "&generator=categorymembers&gcmtype=subcat"
|
+ "&generator=categorymembers&gcmtype=subcat"
|
||||||
+ "&prop=info&gcmlimit=500")
|
+ "&prop=info&gcmlimit=50")
|
||||||
Observable<MwQueryResponse> getSubCategoryList(@Query("gcmtitle") String categoryName);
|
Single<MwQueryResponse> getSubCategoryList(@Query("gcmtitle") String categoryName,
|
||||||
|
@QueryMap(encoded = true) Map<String, String> continuation);
|
||||||
|
|
||||||
@GET("w/api.php?action=query&format=json&formatversion=2"
|
@GET("w/api.php?action=query&format=json&formatversion=2"
|
||||||
+ "&generator=categories&prop=info&gcllimit=500")
|
+ "&generator=categories&prop=info&gcllimit=500")
|
||||||
Observable<MwQueryResponse> getParentCategoryList(@Query("titles") String categoryName);
|
Single<MwQueryResponse> getParentCategoryList(@Query("titles") String categoryName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import fr.free.nrw.commons.category.SubCategoryListFragment;
|
||||||
import fr.free.nrw.commons.contributions.ContributionsFragment;
|
import fr.free.nrw.commons.contributions.ContributionsFragment;
|
||||||
import fr.free.nrw.commons.contributions.ContributionsListFragment;
|
import fr.free.nrw.commons.contributions.ContributionsListFragment;
|
||||||
import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment;
|
import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment;
|
||||||
|
import fr.free.nrw.commons.explore.categories.sub.SubCategoriesFragment;
|
||||||
import fr.free.nrw.commons.explore.depictions.child.ChildDepictionsFragment;
|
import fr.free.nrw.commons.explore.depictions.child.ChildDepictionsFragment;
|
||||||
import fr.free.nrw.commons.explore.depictions.media.DepictedImagesFragment;
|
import fr.free.nrw.commons.explore.depictions.media.DepictedImagesFragment;
|
||||||
import fr.free.nrw.commons.explore.depictions.parent.ParentDepictionsFragment;
|
import fr.free.nrw.commons.explore.depictions.parent.ParentDepictionsFragment;
|
||||||
|
|
@ -99,4 +100,7 @@ public abstract class FragmentBuilderModule {
|
||||||
|
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract CategoriesMediaFragment bindCategoriesMediaFragment();
|
abstract CategoriesMediaFragment bindCategoriesMediaFragment();
|
||||||
|
|
||||||
|
@ContributesAndroidInjector
|
||||||
|
abstract SubCategoriesFragment bindSubCategoriesFragment();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
@ -31,8 +30,7 @@ import java.util.List;
|
||||||
|
|
||||||
public class ExploreActivity
|
public class ExploreActivity
|
||||||
extends NavigationBaseActivity
|
extends NavigationBaseActivity
|
||||||
implements MediaDetailPagerFragment.MediaDetailProvider,
|
implements MediaDetailPagerFragment.MediaDetailProvider, CategoryImagesCallback {
|
||||||
AdapterView.OnItemClickListener, CategoryImagesCallback {
|
|
||||||
|
|
||||||
private static final String FEATURED_IMAGES_CATEGORY = "Featured_pictures_on_Wikimedia_Commons";
|
private static final String FEATURED_IMAGES_CATEGORY = "Featured_pictures_on_Wikimedia_Commons";
|
||||||
private static final String MOBILE_UPLOADS_CATEGORY = "Uploaded_with_Mobile/Android";
|
private static final String MOBILE_UPLOADS_CATEGORY = "Uploaded_with_Mobile/Android";
|
||||||
|
|
@ -177,7 +175,7 @@ public class ExploreActivity
|
||||||
* This method is called onClick of media inside category featured images or mobile uploads.
|
* This method is called onClick of media inside category featured images or mobile uploads.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
public void onMediaClicked( int position) {
|
||||||
tabLayout.setVisibility(View.GONE);
|
tabLayout.setVisibility(View.GONE);
|
||||||
viewPager.setVisibility(View.GONE);
|
viewPager.setVisibility(View.GONE);
|
||||||
mediaContainer.setVisibility(View.VISIBLE);
|
mediaContainer.setVisibility(View.VISIBLE);
|
||||||
|
|
@ -195,7 +193,7 @@ public class ExploreActivity
|
||||||
// coming back to the explore activity. See https://github.com/commons-app/apps-android-commons/issues/1631
|
// coming back to the explore activity. See https://github.com/commons-app/apps-android-commons/issues/1631
|
||||||
// https://stackoverflow.com/questions/11353075/how-can-i-maintain-fragment-state-when-added-to-the-back-stack/19022550#19022550 supportFragmentManager.executePendingTransactions();
|
// https://stackoverflow.com/questions/11353075/how-can-i-maintain-fragment-state-when-added-to-the-back-stack/19022550#19022550 supportFragmentManager.executePendingTransactions();
|
||||||
}
|
}
|
||||||
mediaDetails.showImage(i);
|
mediaDetails.showImage(position);
|
||||||
forceInitBackButton();
|
forceInitBackButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,8 @@ public class SearchActivity extends NavigationBaseActivity
|
||||||
* Open media detail pager fragment on click of image in search results
|
* Open media detail pager fragment on click of image in search results
|
||||||
* @param index item index that should be opened
|
* @param index item index that should be opened
|
||||||
*/
|
*/
|
||||||
public void onSearchImageClicked(int index) {
|
@Override
|
||||||
|
public void onMediaClicked(int index) {
|
||||||
ViewUtil.hideKeyboard(this.findViewById(R.id.searchBox));
|
ViewUtil.hideKeyboard(this.findViewById(R.id.searchBox));
|
||||||
toolbar.setVisibility(View.GONE);
|
toolbar.setVisibility(View.GONE);
|
||||||
tabLayout.setVisibility(View.GONE);
|
tabLayout.setVisibility(View.GONE);
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,18 @@ import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import fr.free.nrw.commons.explore.categories.media.CategoryMediaPresenter
|
import fr.free.nrw.commons.explore.categories.media.CategoryMediaPresenter
|
||||||
import fr.free.nrw.commons.explore.categories.media.CategoryMediaPresenterImpl
|
import fr.free.nrw.commons.explore.categories.media.CategoryMediaPresenterImpl
|
||||||
|
import fr.free.nrw.commons.explore.categories.sub.SubCategoriesPresenter
|
||||||
|
import fr.free.nrw.commons.explore.categories.sub.SubCategoriesPresenterImpl
|
||||||
|
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
abstract class CategoriesModule {
|
abstract class CategoriesModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun CategoryMediaPresenterImpl.bindsParentDepictionPresenter()
|
abstract fun CategoryMediaPresenterImpl.bindsCategoryMediaPresenter()
|
||||||
: CategoryMediaPresenter
|
: CategoryMediaPresenter
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun SubCategoriesPresenterImpl.bindsSubCategoriesPresenter()
|
||||||
|
: SubCategoriesPresenter
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@ package fr.free.nrw.commons.explore.categories.media
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import fr.free.nrw.commons.category.CATEGORY_PREFIX
|
import fr.free.nrw.commons.category.CATEGORY_PREFIX
|
||||||
import fr.free.nrw.commons.category.CategoryDetailsActivity
|
|
||||||
import fr.free.nrw.commons.category.CategoryImagesCallback
|
|
||||||
import fr.free.nrw.commons.explore.media.PageableMediaFragment
|
import fr.free.nrw.commons.explore.media.PageableMediaFragment
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -20,12 +18,4 @@ class CategoriesMediaFragment : PageableMediaFragment() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
onQueryUpdated("$CATEGORY_PREFIX${arguments!!.getString("categoryName")!!}")
|
onQueryUpdated("$CATEGORY_PREFIX${arguments!!.getString("categoryName")!!}")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClicked(position: Int) {
|
|
||||||
(activity as CategoryDetailsActivity).onMediaClicked(position)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyViewPager() {
|
|
||||||
(activity as CategoryImagesCallback).viewPagerNotifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,6 @@ class PageableCategoriesDataSource @Inject constructor(
|
||||||
) : PageableBaseDataSource<String>(liveDataConverter) {
|
) : PageableBaseDataSource<String>(liveDataConverter) {
|
||||||
|
|
||||||
override val loadFunction = { loadSize: Int, startPosition: Int ->
|
override val loadFunction = { loadSize: Int, startPosition: Int ->
|
||||||
categoryClient.searchCategories(query, loadSize, startPosition).blockingFirst()
|
categoryClient.searchCategories(query, loadSize, startPosition).blockingGet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package fr.free.nrw.commons.explore.categories.search
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.R
|
||||||
|
import fr.free.nrw.commons.category.CategoryDetailsActivity
|
||||||
|
import fr.free.nrw.commons.explore.paging.BasePagingFragment
|
||||||
|
|
||||||
|
|
||||||
|
abstract class PageableCategoryFragment : BasePagingFragment<String>() {
|
||||||
|
override val errorTextId: Int = R.string.error_loading_categories
|
||||||
|
override val pagedListAdapter by lazy {
|
||||||
|
PagedSearchCategoriesAdapter {
|
||||||
|
CategoryDetailsActivity.startYourself(context, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,20 +8,12 @@ import javax.inject.Inject
|
||||||
/**
|
/**
|
||||||
* Displays the category search screen.
|
* Displays the category search screen.
|
||||||
*/
|
*/
|
||||||
class SearchCategoryFragment : BasePagingFragment<String>() {
|
class SearchCategoryFragment : PageableCategoryFragment() {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: SearchCategoriesFragmentPresenter
|
lateinit var presenter: SearchCategoriesFragmentPresenter
|
||||||
|
|
||||||
override val errorTextId: Int = R.string.error_loading_categories
|
|
||||||
|
|
||||||
override val injectedPresenter
|
override val injectedPresenter
|
||||||
get() = presenter
|
get() = presenter
|
||||||
|
|
||||||
override val pagedListAdapter by lazy {
|
|
||||||
PagedSearchCategoriesAdapter {
|
|
||||||
CategoryDetailsActivity.startYourself(context, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getEmptyText(query: String) = getString(R.string.categories_not_found, query)
|
override fun getEmptyText(query: String) = getString(R.string.categories_not_found, query)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package fr.free.nrw.commons.explore.categories.sub
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.category.CategoryClient
|
||||||
|
import fr.free.nrw.commons.explore.paging.LiveDataConverter
|
||||||
|
import fr.free.nrw.commons.explore.paging.PageableBaseDataSource
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class PageableSubCategoriesDataSource @Inject constructor(
|
||||||
|
liveDataConverter: LiveDataConverter,
|
||||||
|
val categoryClient: CategoryClient
|
||||||
|
) : PageableBaseDataSource<String>(liveDataConverter) {
|
||||||
|
|
||||||
|
override val loadFunction = { loadSize: Int, startPosition: Int ->
|
||||||
|
if (startPosition == 0) {
|
||||||
|
categoryClient.resetSubCategoryContinuation(query)
|
||||||
|
}
|
||||||
|
categoryClient.getSubCategoryList(query).blockingGet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package fr.free.nrw.commons.explore.categories.sub
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import fr.free.nrw.commons.R
|
||||||
|
import fr.free.nrw.commons.category.CATEGORY_PREFIX
|
||||||
|
import fr.free.nrw.commons.explore.categories.search.PageableCategoryFragment
|
||||||
|
import fr.free.nrw.commons.explore.paging.PagingContract
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
|
class SubCategoriesFragment : PageableCategoryFragment() {
|
||||||
|
|
||||||
|
@Inject lateinit var presenter: SubCategoriesPresenter
|
||||||
|
|
||||||
|
override val injectedPresenter: PagingContract.Presenter<String>
|
||||||
|
get() = presenter
|
||||||
|
|
||||||
|
override fun getEmptyText(query: String) = getString(R.string.no_subcategory_found)
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
onQueryUpdated("$CATEGORY_PREFIX${arguments!!.getString("categoryName")!!}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package fr.free.nrw.commons.explore.categories.sub
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.di.CommonsApplicationModule
|
||||||
|
import fr.free.nrw.commons.explore.paging.BasePagingPresenter
|
||||||
|
import fr.free.nrw.commons.explore.paging.PagingContract
|
||||||
|
import io.reactivex.Scheduler
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Named
|
||||||
|
|
||||||
|
interface SubCategoriesPresenter : PagingContract.Presenter<String>
|
||||||
|
|
||||||
|
class SubCategoriesPresenterImpl @Inject constructor(
|
||||||
|
@Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler,
|
||||||
|
dataSourceFactory: PageableSubCategoriesDataSource
|
||||||
|
) : BasePagingPresenter<String>(mainThreadScheduler, dataSourceFactory),
|
||||||
|
SubCategoriesPresenter
|
||||||
|
|
@ -2,7 +2,6 @@ package fr.free.nrw.commons.explore.depictions.media
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity
|
|
||||||
import fr.free.nrw.commons.explore.media.PageableMediaFragment
|
import fr.free.nrw.commons.explore.media.PageableMediaFragment
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -18,11 +17,4 @@ class DepictedImagesFragment : PageableMediaFragment() {
|
||||||
onQueryUpdated(arguments!!.getString("entityId")!!)
|
onQueryUpdated(arguments!!.getString("entityId")!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClicked(position: Int) {
|
|
||||||
(activity as WikidataItemDetailsActivity).onMediaClicked(position)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyViewPager() {
|
|
||||||
(activity as WikidataItemDetailsActivity).viewPagerNotifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,38 @@
|
||||||
package fr.free.nrw.commons.explore.media
|
package fr.free.nrw.commons.explore.media
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import fr.free.nrw.commons.Media
|
import fr.free.nrw.commons.Media
|
||||||
import fr.free.nrw.commons.R
|
import fr.free.nrw.commons.R
|
||||||
|
import fr.free.nrw.commons.category.CategoryImagesCallback
|
||||||
import fr.free.nrw.commons.explore.paging.BasePagingFragment
|
import fr.free.nrw.commons.explore.paging.BasePagingFragment
|
||||||
|
import fr.free.nrw.commons.media.MediaDetailPagerFragment.MediaDetailProvider
|
||||||
import kotlinx.android.synthetic.main.fragment_search_paginated.*
|
import kotlinx.android.synthetic.main.fragment_search_paginated.*
|
||||||
|
|
||||||
|
|
||||||
abstract class PageableMediaFragment : BasePagingFragment<Media>() {
|
abstract class PageableMediaFragment : BasePagingFragment<Media>(), MediaDetailProvider {
|
||||||
override val pagedListAdapter by lazy { PagedMediaAdapter(::onItemClicked) }
|
|
||||||
|
override val pagedListAdapter by lazy {
|
||||||
|
PagedMediaAdapter {
|
||||||
|
categoryImagesCallback.onMediaClicked(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override val errorTextId: Int = R.string.error_loading_images
|
override val errorTextId: Int = R.string.error_loading_images
|
||||||
|
|
||||||
override fun getEmptyText(query: String) = getString(R.string.no_images_found)
|
override fun getEmptyText(query: String) = getString(R.string.no_images_found)
|
||||||
|
|
||||||
protected abstract fun onItemClicked(position: Int)
|
lateinit var categoryImagesCallback: CategoryImagesCallback
|
||||||
|
|
||||||
protected abstract fun notifyViewPager()
|
override fun onAttach(context: Context) {
|
||||||
|
super.onAttach(context)
|
||||||
|
categoryImagesCallback = (context as CategoryImagesCallback)
|
||||||
|
}
|
||||||
|
|
||||||
private val simpleDataObserver = SimpleDataObserver { notifyViewPager() }
|
private val simpleDataObserver = SimpleDataObserver {
|
||||||
|
categoryImagesCallback.viewPagerNotifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
@ -31,12 +44,12 @@ abstract class PageableMediaFragment : BasePagingFragment<Media>() {
|
||||||
pagedListAdapter.unregisterAdapterDataObserver(simpleDataObserver)
|
pagedListAdapter.unregisterAdapterDataObserver(simpleDataObserver)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMediaAtPosition(position: Int): Media? =
|
override fun getMediaAtPosition(position: Int): Media? =
|
||||||
pagedListAdapter.currentList?.get(position)?.takeIf { it.filename != null }
|
pagedListAdapter.currentList?.get(position)?.takeIf { it.filename != null }
|
||||||
.also {
|
.also {
|
||||||
pagedListAdapter.currentList?.loadAround(position)
|
pagedListAdapter.currentList?.loadAround(position)
|
||||||
paginatedSearchResultsList.scrollToPosition(position)
|
paginatedSearchResultsList.scrollToPosition(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTotalMediaCount(): Int = pagedListAdapter.itemCount
|
override fun getTotalMediaCount(): Int = pagedListAdapter.itemCount
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,15 @@
|
||||||
package fr.free.nrw.commons.explore.media
|
package fr.free.nrw.commons.explore.media
|
||||||
|
|
||||||
import fr.free.nrw.commons.category.CategoryImagesCallback
|
|
||||||
import fr.free.nrw.commons.explore.SearchActivity
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the image search screen.
|
* Displays the image search screen.
|
||||||
*/
|
*/
|
||||||
class SearchMediaFragment : PageableMediaFragment(){
|
class SearchMediaFragment : PageableMediaFragment() {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: SearchMediaFragmentPresenter
|
lateinit var presenter: SearchMediaFragmentPresenter
|
||||||
|
|
||||||
override val injectedPresenter
|
override val injectedPresenter
|
||||||
get() = presenter
|
get() = presenter
|
||||||
|
|
||||||
override fun onItemClicked(position: Int) {
|
|
||||||
(context as SearchActivity).onSearchImageClicked(position)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyViewPager() {
|
|
||||||
(activity as CategoryImagesCallback).viewPagerNotifyDataSetChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -211,5 +211,6 @@ class MediaClient @Inject constructor(
|
||||||
|
|
||||||
fun resetCategoryContinuation(category: String) {
|
fun resetCategoryContinuation(category: String) {
|
||||||
continuationExists.remove("$CATEGORY_CONTINUATION_PREFIX$category")
|
continuationExists.remove("$CATEGORY_CONTINUATION_PREFIX$category")
|
||||||
|
continuationStore.remove("$CATEGORY_CONTINUATION_PREFIX$category")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,8 @@ import categoryItem
|
||||||
import com.nhaarman.mockitokotlin2.mock
|
import com.nhaarman.mockitokotlin2.mock
|
||||||
import com.nhaarman.mockitokotlin2.whenever
|
import com.nhaarman.mockitokotlin2.whenever
|
||||||
import depictedItem
|
import depictedItem
|
||||||
import fr.free.nrw.commons.explore.depictions.DepictsClient
|
|
||||||
import fr.free.nrw.commons.upload.GpsCategoryModel
|
import fr.free.nrw.commons.upload.GpsCategoryModel
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Single
|
||||||
import io.reactivex.subjects.BehaviorSubject
|
import io.reactivex.subjects.BehaviorSubject
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
@ -35,7 +34,7 @@ class CategoriesModelTest {
|
||||||
|
|
||||||
val expectedList = listOf("Test")
|
val expectedList = listOf("Test")
|
||||||
whenever(categoryClient.searchCategoriesForPrefix("tes", 25))
|
whenever(categoryClient.searchCategoriesForPrefix("tes", 25))
|
||||||
.thenReturn(Observable.just(expectedList))
|
.thenReturn(Single.just(expectedList))
|
||||||
|
|
||||||
// Checking if both return "Test"
|
// Checking if both return "Test"
|
||||||
val expectedItems = expectedList.map { CategoryItem(it, false) }
|
val expectedItems = expectedList.map { CategoryItem(it, false) }
|
||||||
|
|
@ -56,7 +55,7 @@ class CategoriesModelTest {
|
||||||
whenever(gpsCategoryModel.categoriesFromLocation)
|
whenever(gpsCategoryModel.categoriesFromLocation)
|
||||||
.thenReturn(BehaviorSubject.createDefault(listOf("gpsCategory")))
|
.thenReturn(BehaviorSubject.createDefault(listOf("gpsCategory")))
|
||||||
whenever(categoryClient.searchCategories("tes", 25))
|
whenever(categoryClient.searchCategories("tes", 25))
|
||||||
.thenReturn(Observable.just(listOf("titleSearch")))
|
.thenReturn(Single.just(listOf("titleSearch")))
|
||||||
whenever(categoryDao.recentCategories(25)).thenReturn(listOf("recentCategories"))
|
whenever(categoryDao.recentCategories(25)).thenReturn(listOf("recentCategories"))
|
||||||
CategoriesModel(categoryClient, categoryDao, gpsCategoryModel)
|
CategoriesModel(categoryClient, categoryDao, gpsCategoryModel)
|
||||||
.searchAll("", listOf("tes"), listOf(depictedItem))
|
.searchAll("", listOf("tes"), listOf(depictedItem))
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,10 @@ package fr.free.nrw.commons.category
|
||||||
|
|
||||||
import com.nhaarman.mockitokotlin2.mock
|
import com.nhaarman.mockitokotlin2.mock
|
||||||
import com.nhaarman.mockitokotlin2.whenever
|
import com.nhaarman.mockitokotlin2.whenever
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Single
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.ArgumentMatchers.anyInt
|
import org.mockito.ArgumentMatchers.*
|
||||||
import org.mockito.ArgumentMatchers.anyString
|
|
||||||
import org.mockito.InjectMocks
|
import org.mockito.InjectMocks
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.mock
|
import org.mockito.Mockito.mock
|
||||||
|
|
@ -32,7 +31,7 @@ class CategoryClientTest {
|
||||||
fun searchCategoriesFound() {
|
fun searchCategoriesFound() {
|
||||||
val mockResponse = withMockResponse("Category:Test")
|
val mockResponse = withMockResponse("Category:Test")
|
||||||
whenever(categoryInterface.searchCategories(anyString(), anyInt(), anyInt()))
|
whenever(categoryInterface.searchCategories(anyString(), anyInt(), anyInt()))
|
||||||
.thenReturn(Observable.just(mockResponse))
|
.thenReturn(Single.just(mockResponse))
|
||||||
categoryClient.searchCategories("tes", 10)
|
categoryClient.searchCategories("tes", 10)
|
||||||
.test()
|
.test()
|
||||||
.assertValues(listOf("Test"))
|
.assertValues(listOf("Test"))
|
||||||
|
|
@ -45,7 +44,7 @@ class CategoryClientTest {
|
||||||
fun searchCategoriesNull() {
|
fun searchCategoriesNull() {
|
||||||
val mockResponse = withNullPages()
|
val mockResponse = withNullPages()
|
||||||
whenever(categoryInterface.searchCategories(anyString(), anyInt(), anyInt()))
|
whenever(categoryInterface.searchCategories(anyString(), anyInt(), anyInt()))
|
||||||
.thenReturn(Observable.just(mockResponse))
|
.thenReturn(Single.just(mockResponse))
|
||||||
categoryClient.searchCategories("tes", 10)
|
categoryClient.searchCategories("tes", 10)
|
||||||
.test()
|
.test()
|
||||||
.assertValues(emptyList())
|
.assertValues(emptyList())
|
||||||
|
|
@ -58,7 +57,7 @@ class CategoryClientTest {
|
||||||
fun searchCategoriesForPrefixFound() {
|
fun searchCategoriesForPrefixFound() {
|
||||||
val mockResponse = withMockResponse("Category:Test")
|
val mockResponse = withMockResponse("Category:Test")
|
||||||
whenever(categoryInterface.searchCategoriesForPrefix(anyString(), anyInt(), anyInt()))
|
whenever(categoryInterface.searchCategoriesForPrefix(anyString(), anyInt(), anyInt()))
|
||||||
.thenReturn(Observable.just(mockResponse))
|
.thenReturn(Single.just(mockResponse))
|
||||||
categoryClient.searchCategoriesForPrefix("tes", 10)
|
categoryClient.searchCategoriesForPrefix("tes", 10)
|
||||||
.test()
|
.test()
|
||||||
.assertValues(listOf("Test"))
|
.assertValues(listOf("Test"))
|
||||||
|
|
@ -71,7 +70,7 @@ class CategoryClientTest {
|
||||||
fun searchCategoriesForPrefixNull() {
|
fun searchCategoriesForPrefixNull() {
|
||||||
val mockResponse = withNullPages()
|
val mockResponse = withNullPages()
|
||||||
whenever(categoryInterface.searchCategoriesForPrefix(anyString(), anyInt(), anyInt()))
|
whenever(categoryInterface.searchCategoriesForPrefix(anyString(), anyInt(), anyInt()))
|
||||||
.thenReturn(Observable.just(mockResponse))
|
.thenReturn(Single.just(mockResponse))
|
||||||
categoryClient.searchCategoriesForPrefix("tes", 10)
|
categoryClient.searchCategoriesForPrefix("tes", 10)
|
||||||
.test()
|
.test()
|
||||||
.assertValues(emptyList())
|
.assertValues(emptyList())
|
||||||
|
|
@ -84,7 +83,7 @@ class CategoryClientTest {
|
||||||
fun getParentCategoryListFound() {
|
fun getParentCategoryListFound() {
|
||||||
val mockResponse = withMockResponse("Category:Test")
|
val mockResponse = withMockResponse("Category:Test")
|
||||||
whenever(categoryInterface.getParentCategoryList(anyString()))
|
whenever(categoryInterface.getParentCategoryList(anyString()))
|
||||||
.thenReturn(Observable.just(mockResponse))
|
.thenReturn(Single.just(mockResponse))
|
||||||
categoryClient.getParentCategoryList("tes")
|
categoryClient.getParentCategoryList("tes")
|
||||||
.test()
|
.test()
|
||||||
.assertValues(listOf("Test"))
|
.assertValues(listOf("Test"))
|
||||||
|
|
@ -94,7 +93,7 @@ class CategoryClientTest {
|
||||||
fun getParentCategoryListNull() {
|
fun getParentCategoryListNull() {
|
||||||
val mockResponse = withNullPages()
|
val mockResponse = withNullPages()
|
||||||
whenever(categoryInterface.getParentCategoryList(anyString()))
|
whenever(categoryInterface.getParentCategoryList(anyString()))
|
||||||
.thenReturn(Observable.just(mockResponse))
|
.thenReturn(Single.just(mockResponse))
|
||||||
categoryClient.getParentCategoryList("tes")
|
categoryClient.getParentCategoryList("tes")
|
||||||
.test()
|
.test()
|
||||||
.assertValues(emptyList())
|
.assertValues(emptyList())
|
||||||
|
|
@ -103,8 +102,8 @@ class CategoryClientTest {
|
||||||
@Test
|
@Test
|
||||||
fun getSubCategoryListFound() {
|
fun getSubCategoryListFound() {
|
||||||
val mockResponse = withMockResponse("Category:Test")
|
val mockResponse = withMockResponse("Category:Test")
|
||||||
whenever(categoryInterface.getSubCategoryList("tes"))
|
whenever(categoryInterface.getSubCategoryList("tes", emptyMap()))
|
||||||
.thenReturn(Observable.just(mockResponse))
|
.thenReturn(Single.just(mockResponse))
|
||||||
categoryClient.getSubCategoryList("tes")
|
categoryClient.getSubCategoryList("tes")
|
||||||
.test()
|
.test()
|
||||||
.assertValues(listOf("Test"))
|
.assertValues(listOf("Test"))
|
||||||
|
|
@ -113,8 +112,11 @@ class CategoryClientTest {
|
||||||
@Test
|
@Test
|
||||||
fun getSubCategoryListNull() {
|
fun getSubCategoryListNull() {
|
||||||
val mockResponse = withNullPages()
|
val mockResponse = withNullPages()
|
||||||
whenever(categoryInterface.getSubCategoryList(anyString()))
|
whenever(categoryInterface.getSubCategoryList(
|
||||||
.thenReturn(Observable.just(mockResponse))
|
anyString(),
|
||||||
|
anyMap()
|
||||||
|
))
|
||||||
|
.thenReturn(Single.just(mockResponse))
|
||||||
categoryClient.getSubCategoryList("tes")
|
categoryClient.getSubCategoryList("tes")
|
||||||
.test()
|
.test()
|
||||||
.assertValues(emptyList())
|
.assertValues(emptyList())
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package fr.free.nrw.commons.explore.categories.sub
|
||||||
|
|
||||||
|
import com.nhaarman.mockitokotlin2.never
|
||||||
|
import com.nhaarman.mockitokotlin2.verify
|
||||||
|
import com.nhaarman.mockitokotlin2.whenever
|
||||||
|
import fr.free.nrw.commons.category.CategoryClient
|
||||||
|
import fr.free.nrw.commons.explore.paging.LiveDataConverter
|
||||||
|
import io.reactivex.Single
|
||||||
|
import org.hamcrest.CoreMatchers.`is`
|
||||||
|
import org.hamcrest.MatcherAssert.assertThat
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
class PageableSubCategoriesDataSourceTest{
|
||||||
|
@Mock
|
||||||
|
lateinit var categoryClient: CategoryClient
|
||||||
|
@Mock
|
||||||
|
lateinit var liveDataConverter: LiveDataConverter
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `loadFunction calls reset at position 0`() {
|
||||||
|
val dataSource =
|
||||||
|
PageableSubCategoriesDataSource(liveDataConverter, categoryClient)
|
||||||
|
dataSource.onQueryUpdated("test")
|
||||||
|
whenever(categoryClient.getSubCategoryList("test"))
|
||||||
|
.thenReturn(Single.just(emptyList()))
|
||||||
|
assertThat(dataSource.loadFunction(-1, 0), `is`(emptyList()))
|
||||||
|
verify(categoryClient).resetSubCategoryContinuation("test")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `loadFunction does not call reset at any other position`() {
|
||||||
|
val dataSource =
|
||||||
|
PageableSubCategoriesDataSource(liveDataConverter, categoryClient)
|
||||||
|
dataSource.onQueryUpdated("test")
|
||||||
|
whenever(categoryClient.getSubCategoryList("test"))
|
||||||
|
.thenReturn(Single.just(emptyList()))
|
||||||
|
assertThat(dataSource.loadFunction(-1, 1), `is`(emptyList()))
|
||||||
|
verify(categoryClient, never()).resetSubCategoryContinuation("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ import com.nhaarman.mockitokotlin2.mock
|
||||||
import com.nhaarman.mockitokotlin2.whenever
|
import com.nhaarman.mockitokotlin2.whenever
|
||||||
import fr.free.nrw.commons.category.CategoryClient
|
import fr.free.nrw.commons.category.CategoryClient
|
||||||
import fr.free.nrw.commons.explore.categories.search.PageableCategoriesDataSource
|
import fr.free.nrw.commons.explore.categories.search.PageableCategoriesDataSource
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Single
|
||||||
import org.hamcrest.MatcherAssert.assertThat
|
import org.hamcrest.MatcherAssert.assertThat
|
||||||
import org.hamcrest.Matchers
|
import org.hamcrest.Matchers
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
@ -14,7 +14,7 @@ class PageableCategoriesDataSourceTest {
|
||||||
fun `loadFunction loads categories`() {
|
fun `loadFunction loads categories`() {
|
||||||
val categoryClient: CategoryClient = mock()
|
val categoryClient: CategoryClient = mock()
|
||||||
whenever(categoryClient.searchCategories("test", 0, 1))
|
whenever(categoryClient.searchCategories("test", 0, 1))
|
||||||
.thenReturn(Observable.just(emptyList()))
|
.thenReturn(Single.just(emptyList()))
|
||||||
val pageableCategoriesDataSource = PageableCategoriesDataSource(mock(), categoryClient)
|
val pageableCategoriesDataSource = PageableCategoriesDataSource(mock(), categoryClient)
|
||||||
pageableCategoriesDataSource.onQueryUpdated("test")
|
pageableCategoriesDataSource.onQueryUpdated("test")
|
||||||
assertThat(pageableCategoriesDataSource.loadFunction(0, 1), Matchers.`is`(emptyList()))
|
assertThat(pageableCategoriesDataSource.loadFunction(0, 1), Matchers.`is`(emptyList()))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue