diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/BookmarksActivity.java b/app/src/main/java/fr/free/nrw/commons/bookmarks/BookmarksActivity.java index 2dfeb8b86..e16ec6d31 100644 --- a/app/src/main/java/fr/free/nrw/commons/bookmarks/BookmarksActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/BookmarksActivity.java @@ -141,5 +141,7 @@ public class BookmarksActivity extends NavigationBaseActivity } @Override - public void requestMoreImages() { } + public void onMediaClicked(int position) { + //TODO use with pagination + } } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt index 48ac1fc7c..ab11b9863 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.kt @@ -93,6 +93,7 @@ class CategoriesModel @Inject constructor( else categoryClient.searchCategoriesForPrefix(term.toLowerCase(), SEARCH_CATS_LIMIT) .map { it.sortedWith(StringSortingUtils.sortBySimilarity(term)) } + .toObservable() } private fun categoriesFromDepiction(selectedDepictions: List) = @@ -126,7 +127,7 @@ class CategoriesModel @Inject constructor( * @return */ private fun getTitleCategories(title: String): Observable> { - return categoryClient.searchCategories(title.toLowerCase(), SEARCH_CATS_LIMIT) + return categoryClient.searchCategories(title.toLowerCase(), SEARCH_CATS_LIMIT).toObservable() } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt index 3750229db..aeb62b127 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt @@ -1,16 +1,21 @@ package fr.free.nrw.commons.category -import io.reactivex.Observable +import io.reactivex.Single import org.wikipedia.dataclient.mwapi.MwQueryResponse import javax.inject.Inject import javax.inject.Singleton const val CATEGORY_PREFIX = "Category:" +const val SUB_CATEGORY_CONTINUATION_PREFIX = "sub_category_" +const val PARENT_CATEGORY_CONTINUATION_PREFIX = "parent_category_" + /** * Category Client to handle custom calls to Commons MediaWiki APIs */ @Singleton -class CategoryClient @Inject constructor(private val categoryInterface: CategoryInterface) { +class CategoryClient @Inject constructor(private val categoryInterface: CategoryInterface) : + ContinuationClient() { + /** * Searches for categories containing the specified string. * @@ -21,8 +26,8 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category */ @JvmOverloads fun searchCategories(filter: String?, itemLimit: Int, offset: Int = 0): - Observable> { - return responseToCategoryName(categoryInterface.searchCategories(filter, itemLimit, offset)) + Single> { + return responseMapper(categoryInterface.searchCategories(filter, itemLimit, offset)) } /** @@ -35,8 +40,8 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category */ @JvmOverloads fun searchCategoriesForPrefix(prefix: String?, itemLimit: Int, offset: Int = 0): - Observable> { - return responseToCategoryName( + Single> { + return responseMapper( categoryInterface.searchCategoriesForPrefix(prefix, itemLimit, offset) ) } @@ -48,8 +53,12 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category * @param categoryName Category name as defined on commons * @return Observable emitting the categories returned. If our search yielded "Category:Test", "Test" is emitted. */ - fun getSubCategoryList(categoryName: String?): Observable> { - return responseToCategoryName(categoryInterface.getSubCategoryList(categoryName)) + fun getSubCategoryList(categoryName: String): Single> { + return continuationRequest(SUB_CATEGORY_CONTINUATION_PREFIX, categoryName) { + categoryInterface.getSubCategoryList( + categoryName, it + ) + } } /** @@ -59,19 +68,29 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category * @param categoryName Category name as defined on commons * @return */ - fun getParentCategoryList(categoryName: String?): Observable> { - return responseToCategoryName(categoryInterface.getParentCategoryList(categoryName)) + fun getParentCategoryList(categoryName: String): Single> { + return continuationRequest(PARENT_CATEGORY_CONTINUATION_PREFIX, categoryName) { + categoryInterface.getParentCategoryList(categoryName, it) + } } - /** - * Internal function to reduce code reuse. Extracts the categories returned from MwQueryResponse. - * - * @param responseObservable The query response observable - * @return Observable emitting the categories returned. If our search yielded "Category:Test", "Test" is emitted. - */ - private fun responseToCategoryName(responseObservable: Observable): Observable> { - return responseObservable - .map { it.query()?.pages() ?: emptyList() } + fun resetSubCategoryContinuation(category: String) { + resetContinuation(SUB_CATEGORY_CONTINUATION_PREFIX, category) + } + + fun resetParentCategoryContinuation(category: String) { + resetContinuation(PARENT_CATEGORY_CONTINUATION_PREFIX, category) + } + + override fun responseMapper( + networkResult: Single, + key: String? + ): Single> { + return networkResult + .map { + handleContinuationResponse(it.continuation(), key) + it.query()?.pages() ?: emptyList() + } .map { it.map { page -> page.title().replace(CATEGORY_PREFIX, "") } } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.java index 02af44c49..ed085fc37 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.java @@ -20,6 +20,8 @@ import fr.free.nrw.commons.R; import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.explore.ViewPagerAdapter; import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment; +import fr.free.nrw.commons.explore.categories.parent.ParentCategoriesFragment; +import fr.free.nrw.commons.explore.categories.sub.SubCategoriesFragment; import fr.free.nrw.commons.media.MediaDetailPagerFragment; import fr.free.nrw.commons.theme.NavigationBaseActivity; import java.util.ArrayList; @@ -69,25 +71,21 @@ public class CategoryDetailsActivity extends NavigationBaseActivity List fragmentList = new ArrayList<>(); List titleList = new ArrayList<>(); categoriesMediaFragment = new CategoriesMediaFragment(); - SubCategoryListFragment subCategoryListFragment = new SubCategoryListFragment(); - SubCategoryListFragment parentCategoryListFragment = new SubCategoryListFragment(); + SubCategoriesFragment subCategoryListFragment = new SubCategoriesFragment(); + ParentCategoriesFragment parentCategoriesFragment = new ParentCategoriesFragment(); categoryName = getIntent().getStringExtra("categoryName"); if (getIntent() != null && categoryName != null) { Bundle arguments = new Bundle(); arguments.putString("categoryName", categoryName); - arguments.putBoolean("isParentCategory", false); categoriesMediaFragment.setArguments(arguments); subCategoryListFragment.setArguments(arguments); - Bundle parentCategoryArguments = new Bundle(); - parentCategoryArguments.putString("categoryName", categoryName); - parentCategoryArguments.putBoolean("isParentCategory", true); - parentCategoryListFragment.setArguments(parentCategoryArguments); + parentCategoriesFragment.setArguments(arguments); } fragmentList.add(categoriesMediaFragment); titleList.add("MEDIA"); fragmentList.add(subCategoryListFragment); titleList.add("SUBCATEGORIES"); - fragmentList.add(parentCategoryListFragment); + fragmentList.add(parentCategoriesFragment); titleList.add("PARENT CATEGORIES"); viewPagerAdapter.setTabData(fragmentList, titleList); viewPagerAdapter.notifyDataSetChanged(); @@ -133,7 +131,6 @@ public class CategoryDetailsActivity extends NavigationBaseActivity */ public static void startYourself(Context context, String categoryName) { Intent intent = new Intent(context, CategoryDetailsActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.putExtra("categoryName", categoryName); context.startActivity(intent); } @@ -212,12 +209,4 @@ public class CategoryDetailsActivity extends NavigationBaseActivity } } - /** - * This method is called when viewPager has reached its end. - * Fetches more images using search query and adds it to the grid view and viewpager adapter - */ - @Override - public void requestMoreImages() { - //unneeded - } } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesActivity.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesActivity.java index c7c59ad3d..058aa397f 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesActivity.java @@ -187,12 +187,8 @@ public class CategoryImagesActivity } } - /** - * This method is called when viewPager has reached its end. - * Fetches more images using search query and adds it to the gridView and viewpager adapter - */ @Override - public void requestMoreImages() { - //unneeded + public void onMediaClicked(int position) { + // this class is unused and will be deleted } } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesCallback.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesCallback.java index e93e74fdf..5b85a2f81 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesCallback.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesCallback.java @@ -7,7 +7,7 @@ package fr.free.nrw.commons.category; public interface CategoryImagesCallback { void viewPagerNotifyDataSetChanged(); - void requestMoreImages(); + void onMediaClicked(int position); } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryInterface.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryInterface.java index f03506ed4..a9f030dec 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryInterface.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryInterface.java @@ -1,10 +1,11 @@ package fr.free.nrw.commons.category; +import io.reactivex.Single; +import java.util.Map; import org.wikipedia.dataclient.mwapi.MwQueryResponse; - -import io.reactivex.Observable; import retrofit2.http.GET; import retrofit2.http.Query; +import retrofit2.http.QueryMap; /** * 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" + "&generator=search&gsrnamespace=14") - Observable searchCategories(@Query("gsrsearch") String filter, + Single searchCategories(@Query("gsrsearch") String filter, @Query("gsrlimit") int itemLimit, @Query("gsroffset") int offset); /** @@ -32,16 +33,18 @@ public interface CategoryInterface { */ @GET("w/api.php?action=query&format=json&formatversion=2" + "&generator=allcategories") - Observable searchCategoriesForPrefix(@Query("gacprefix") String prefix, + Single searchCategoriesForPrefix(@Query("gacprefix") String prefix, @Query("gaclimit") int itemLimit, @Query("gacoffset") int offset); @GET("w/api.php?action=query&format=json&formatversion=2" + "&generator=categorymembers&gcmtype=subcat" - + "&prop=info&gcmlimit=500") - Observable getSubCategoryList(@Query("gcmtitle") String categoryName); + + "&prop=info&gcmlimit=50") + Single getSubCategoryList(@Query("gcmtitle") String categoryName, + @QueryMap(encoded = true) Map continuation); @GET("w/api.php?action=query&format=json&formatversion=2" - + "&generator=categories&prop=info&gcllimit=500") - Observable getParentCategoryList(@Query("titles") String categoryName); + + "&generator=categories&prop=info&gcllimit=50") + Single getParentCategoryList(@Query("titles") String categoryName, + @QueryMap(encoded = true) Map continuation); } diff --git a/app/src/main/java/fr/free/nrw/commons/category/ContinuationClient.kt b/app/src/main/java/fr/free/nrw/commons/category/ContinuationClient.kt new file mode 100644 index 000000000..cbf9017b2 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/category/ContinuationClient.kt @@ -0,0 +1,41 @@ +package fr.free.nrw.commons.category + +import io.reactivex.Single + + +abstract class ContinuationClient { + private val continuationStore: MutableMap?> = mutableMapOf() + private val continuationExists: MutableMap = mutableMapOf() + + private fun hasMorePagesFor(key: String) = continuationExists[key] ?: true + fun continuationRequest( + prefix: String, + name: String, + requestFunction: (Map) -> Single + ): Single> { + val key = "$prefix$name" + return if (hasMorePagesFor(key)) { + responseMapper(requestFunction(continuationStore[key] ?: emptyMap()), key) + } else { + Single.just(emptyList()) + } + } + + abstract fun responseMapper(networkResult: Single, key: String?=null): Single> + + fun handleContinuationResponse(continuation:Map?, key:String?){ + if (key != null) { + continuationExists[key] = + continuation?.let { continuation -> + continuationStore[key] = continuation + true + } ?: false + } + } + + protected fun resetContinuation(prefix: String, category: String) { + continuationExists.remove("$prefix$category") + continuationStore.remove("$prefix$category") + } + +} diff --git a/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java b/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java deleted file mode 100644 index d5f33a20f..000000000 --- a/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java +++ /dev/null @@ -1,154 +0,0 @@ -package fr.free.nrw.commons.category; - - -import static android.view.View.GONE; -import static android.view.View.VISIBLE; -import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_PREFIX; - -import android.content.Intent; -import android.content.res.Configuration; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.TextView; -import androidx.recyclerview.widget.GridLayoutManager; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import butterknife.BindView; -import butterknife.ButterKnife; -import fr.free.nrw.commons.R; -import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; -import fr.free.nrw.commons.explore.categories.search.SearchCategoriesAdapter; -import fr.free.nrw.commons.utils.NetworkUtils; -import fr.free.nrw.commons.utils.ViewUtil; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; -import java.util.List; -import javax.inject.Inject; -import kotlin.Unit; -import timber.log.Timber; - -/** - * Displays the category search screen. - */ - -public class SubCategoryListFragment extends CommonsDaggerSupportFragment { - - @BindView(R.id.imagesListBox) - RecyclerView categoriesRecyclerView; - @BindView(R.id.imageSearchInProgress) - ProgressBar progressBar; - @BindView(R.id.imagesNotFound) - TextView categoriesNotFoundView; - - private String categoryName = null; - @Inject CategoryClient categoryClient; - - private SearchCategoriesAdapter categoriesAdapter; - private boolean isParentCategory = true; - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_browse_image, container, false); - ButterKnife.bind(this, rootView); - categoryName = getArguments().getString("categoryName"); - isParentCategory = getArguments().getBoolean("isParentCategory"); - initSubCategoryList(); - if (getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){ - categoriesRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - } - else{ - categoriesRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2)); - } - categoriesAdapter = new SearchCategoriesAdapter(item->{ - Intent intent = new Intent(getContext(), CategoryDetailsActivity.class); - intent.putExtra("categoryName", item); - getContext().startActivity(intent); - return Unit.INSTANCE; - }); - categoriesRecyclerView.setAdapter(categoriesAdapter); - return rootView; - } - - /** - * Checks for internet connection and then initializes the recycler view with all(max 500) categories of the searched query - * Clearing categoryAdapter every time new keyword is searched so that user can see only new results - */ - public void initSubCategoryList() { - categoriesNotFoundView.setVisibility(GONE); - if (!NetworkUtils.isInternetConnectionEstablished(getContext())) { - handleNoInternet(); - return; - } - progressBar.setVisibility(View.VISIBLE); - if (isParentCategory) { - compositeDisposable.add(categoryClient.getParentCategoryList( - CATEGORY_PREFIX +categoryName) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::handleSuccess, this::handleError)); - } else { - compositeDisposable.add(categoryClient.getSubCategoryList( - CATEGORY_PREFIX +categoryName) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::handleSuccess, this::handleError)); - } - } - - - /** - * Handles the success scenario - * it initializes the recycler view by adding items to the adapter - * @param subCategoryList - */ - private void handleSuccess(List subCategoryList) { - if (subCategoryList == null || subCategoryList.isEmpty()) { - initEmptyView(); - } - else { - progressBar.setVisibility(View.GONE); - categoriesAdapter.addAll(subCategoryList); - categoriesAdapter.notifyDataSetChanged(); - } - } - - /** - * Logs and handles API error scenario - * @param throwable - */ - private void handleError(Throwable throwable) { - if (!isParentCategory){ - Timber.e(throwable, "Error occurred while loading queried subcategories"); - ViewUtil.showShortSnackbar(categoriesRecyclerView,R.string.error_loading_categories); - }else { - Timber.e(throwable, "Error occurred while loading queried parentcategories"); - ViewUtil.showShortSnackbar(categoriesRecyclerView,R.string.error_loading_categories); - } - } - - /** - * Handles the UI updates for a empty results scenario - */ - private void initEmptyView() { - progressBar.setVisibility(GONE); - categoriesNotFoundView.setVisibility(VISIBLE); - if (!isParentCategory){ - categoriesNotFoundView.setText(getString(R.string.no_subcategory_found)); - }else { - categoriesNotFoundView.setText(getString(R.string.no_parentcategory_found)); - } - - } - - /** - * Handles the UI updates for no internet scenario - */ - private void handleNoInternet() { - progressBar.setVisibility(GONE); - ViewUtil.showShortSnackbar(categoriesRecyclerView, R.string.no_internet); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionBoundaryCallback.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionBoundaryCallback.kt index a001da3ca..44b1a35fb 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionBoundaryCallback.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionBoundaryCallback.kt @@ -51,9 +51,6 @@ class ContributionBoundaryCallback @Inject constructor( * Fetches contributions using the MediaWiki API */ fun fetchContributions() { - if (mediaClient.doesMediaListForUserHaveMorePages(sessionManager.userName!!).not()) { - return - } compositeDisposable.add( mediaClient.getMediaListForUser(sessionManager.userName!!) .map { mediaList: List -> diff --git a/app/src/main/java/fr/free/nrw/commons/di/FragmentBuilderModule.java b/app/src/main/java/fr/free/nrw/commons/di/FragmentBuilderModule.java index ff0526da1..75359588b 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/FragmentBuilderModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/FragmentBuilderModule.java @@ -4,14 +4,15 @@ import dagger.Module; import dagger.android.ContributesAndroidInjector; import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsFragment; import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesFragment; -import fr.free.nrw.commons.category.SubCategoryListFragment; import fr.free.nrw.commons.contributions.ContributionsFragment; import fr.free.nrw.commons.contributions.ContributionsListFragment; import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment; +import fr.free.nrw.commons.explore.categories.parent.ParentCategoriesFragment; +import fr.free.nrw.commons.explore.categories.search.SearchCategoryFragment; +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.media.DepictedImagesFragment; import fr.free.nrw.commons.explore.depictions.parent.ParentDepictionsFragment; -import fr.free.nrw.commons.explore.categories.search.SearchCategoryFragment; import fr.free.nrw.commons.explore.depictions.search.SearchDepictionsFragment; import fr.free.nrw.commons.explore.media.SearchMediaFragment; import fr.free.nrw.commons.explore.recentsearches.RecentSearchesFragment; @@ -28,7 +29,7 @@ import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment; /** * This Class Represents the Module for dependency injection (using dagger) * so, if a developer needs to add a new Fragment to the commons app - * then that must be mentioned here to inject the dependencies + * then that must be mentioned here to inject the dependencies */ @Module @SuppressWarnings({"WeakerAccess", "unused"}) @@ -49,9 +50,6 @@ public abstract class FragmentBuilderModule { @ContributesAndroidInjector abstract DepictedImagesFragment bindDepictedImagesFragment(); - @ContributesAndroidInjector - abstract SubCategoryListFragment bindSubCategoryListFragment(); - @ContributesAndroidInjector abstract SearchMediaFragment bindBrowseImagesListFragment(); @@ -99,4 +97,10 @@ public abstract class FragmentBuilderModule { @ContributesAndroidInjector abstract CategoriesMediaFragment bindCategoriesMediaFragment(); + + @ContributesAndroidInjector + abstract SubCategoriesFragment bindSubCategoriesFragment(); + + @ContributesAndroidInjector + abstract ParentCategoriesFragment bindParentCategoriesFragment(); } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/ExploreActivity.java b/app/src/main/java/fr/free/nrw/commons/explore/ExploreActivity.java index 4140b248e..485c716fc 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/ExploreActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/ExploreActivity.java @@ -7,7 +7,6 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.widget.AdapterView; import android.widget.FrameLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -31,8 +30,7 @@ import java.util.List; public class ExploreActivity extends NavigationBaseActivity - implements MediaDetailPagerFragment.MediaDetailProvider, - AdapterView.OnItemClickListener, CategoryImagesCallback { + implements MediaDetailPagerFragment.MediaDetailProvider, CategoryImagesCallback { private static final String FEATURED_IMAGES_CATEGORY = "Featured_pictures_on_Wikimedia_Commons"; private static final String MOBILE_UPLOADS_CATEGORY = "Uploaded_with_Mobile/Android"; @@ -163,21 +161,11 @@ public class ExploreActivity super.onBackPressed(); } - - /** - * This method is called when viewPager has reached its end. - * Fetches more images and adds them to the recycler view and viewpager adapter - */ - @Override - public void requestMoreImages() { - //unneeded - } - /** * This method is called onClick of media inside category featured images or mobile uploads. */ @Override - public void onItemClick(AdapterView adapterView, View view, int i, long l) { + public void onMediaClicked( int position) { tabLayout.setVisibility(View.GONE); viewPager.setVisibility(View.GONE); mediaContainer.setVisibility(View.VISIBLE); @@ -195,7 +183,7 @@ public class ExploreActivity // 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(); } - mediaDetails.showImage(i); + mediaDetails.showImage(position); forceInitBackButton(); } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/SearchActivity.java b/app/src/main/java/fr/free/nrw/commons/explore/SearchActivity.java index 1264d87b3..89bebc090 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/SearchActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/SearchActivity.java @@ -191,7 +191,8 @@ public class SearchActivity extends NavigationBaseActivity * Open media detail pager fragment on click of image in search results * @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)); toolbar.setVisibility(View.GONE); tabLayout.setVisibility(View.GONE); @@ -263,15 +264,6 @@ public class SearchActivity extends NavigationBaseActivity viewPager.requestFocus(); } - /** - * This method is called when viewPager has reached its end. - * Fetches more images using search query and adds it to the recycler view and viewpager adapter - */ - @Override - public void requestMoreImages() { - //unneeded - } - @Override protected void onDestroy() { super.onDestroy(); //Dispose the disposables when the activity is destroyed diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/CategoriesModule.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/CategoriesModule.kt index 1022c4ad4..394b88ca6 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/CategoriesModule.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/CategoriesModule.kt @@ -4,12 +4,24 @@ import dagger.Binds import dagger.Module 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.parent.ParentCategoriesPresenter +import fr.free.nrw.commons.explore.categories.parent.ParentCategoriesPresenterImpl +import fr.free.nrw.commons.explore.categories.sub.SubCategoriesPresenter +import fr.free.nrw.commons.explore.categories.sub.SubCategoriesPresenterImpl @Module abstract class CategoriesModule { @Binds - abstract fun CategoryMediaPresenterImpl.bindsParentDepictionPresenter() + abstract fun CategoryMediaPresenterImpl.bindsCategoryMediaPresenter() : CategoryMediaPresenter + + @Binds + abstract fun SubCategoriesPresenterImpl.bindsSubCategoriesPresenter() + : SubCategoriesPresenter + + @Binds + abstract fun ParentCategoriesPresenterImpl.bindsParentCategoriesPresenter() + : ParentCategoriesPresenter } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/PageableCategoryFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/PageableCategoryFragment.kt new file mode 100644 index 000000000..54a97cb09 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/PageableCategoryFragment.kt @@ -0,0 +1,15 @@ +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.paging.BasePagingFragment + + +abstract class PageableCategoryFragment : BasePagingFragment() { + override val errorTextId: Int = R.string.error_loading_categories + override val pagedListAdapter by lazy { + PagedSearchCategoriesAdapter { + CategoryDetailsActivity.startYourself(context, it) + } + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/PagedSearchCategoriesAdapter.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/PagedCategoriesAdapter.kt similarity index 96% rename from app/src/main/java/fr/free/nrw/commons/explore/categories/search/PagedSearchCategoriesAdapter.kt rename to app/src/main/java/fr/free/nrw/commons/explore/categories/PagedCategoriesAdapter.kt index 220339180..738092495 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/PagedSearchCategoriesAdapter.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/PagedCategoriesAdapter.kt @@ -1,4 +1,4 @@ -package fr.free.nrw.commons.explore.categories.search +package fr.free.nrw.commons.explore.categories import android.view.View import android.view.ViewGroup @@ -41,5 +41,3 @@ class CategoryItemViewHolder(containerView: View, val onCategoryClicked: (String textView1.text = item.substringAfter(CATEGORY_PREFIX) } } - - diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/media/CategoriesMediaFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/media/CategoriesMediaFragment.kt index 9347c90d8..8e39781ec 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/media/CategoriesMediaFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/media/CategoriesMediaFragment.kt @@ -3,8 +3,6 @@ package fr.free.nrw.commons.explore.categories.media import android.os.Bundle import android.view.View 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 javax.inject.Inject @@ -20,12 +18,4 @@ class CategoriesMediaFragment : PageableMediaFragment() { super.onViewCreated(view, savedInstanceState) onQueryUpdated("$CATEGORY_PREFIX${arguments!!.getString("categoryName")!!}") } - - override fun onItemClicked(position: Int) { - (activity as CategoryDetailsActivity).onMediaClicked(position) - } - - override fun notifyViewPager() { - (activity as CategoryImagesCallback).viewPagerNotifyDataSetChanged() - } } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/parent/PageableParentCategoriesDataSource.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/parent/PageableParentCategoriesDataSource.kt new file mode 100644 index 000000000..24d2356e6 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/parent/PageableParentCategoriesDataSource.kt @@ -0,0 +1,19 @@ +package fr.free.nrw.commons.explore.categories.parent + +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 PageableParentCategoriesDataSource @Inject constructor( + liveDataConverter: LiveDataConverter, + val categoryClient: CategoryClient +) : PageableBaseDataSource(liveDataConverter) { + + override val loadFunction = { loadSize: Int, startPosition: Int -> + if (startPosition == 0) { + categoryClient.resetParentCategoryContinuation(query) + } + categoryClient.getParentCategoryList(query).blockingGet() + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/parent/ParentCategoriesFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/parent/ParentCategoriesFragment.kt new file mode 100644 index 000000000..a43fdad1d --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/parent/ParentCategoriesFragment.kt @@ -0,0 +1,26 @@ +package fr.free.nrw.commons.explore.categories.parent + +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.PageableCategoryFragment +import javax.inject.Inject + + +class ParentCategoriesFragment : PageableCategoryFragment() { + + @Inject + lateinit var presenter: ParentCategoriesPresenter + + override val injectedPresenter + get() = presenter + + override fun getEmptyText(query: String) = getString(R.string.no_parentcategory_found) + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + onQueryUpdated("$CATEGORY_PREFIX${arguments!!.getString("categoryName")!!}") + } +} + diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/parent/ParentCategoriesPresenterImpl.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/parent/ParentCategoriesPresenterImpl.kt new file mode 100644 index 000000000..90c11d10d --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/parent/ParentCategoriesPresenterImpl.kt @@ -0,0 +1,17 @@ +package fr.free.nrw.commons.explore.categories.parent + +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 ParentCategoriesPresenter : PagingContract.Presenter + +class ParentCategoriesPresenterImpl @Inject constructor( + @Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler, + dataSourceFactory: PageableParentCategoriesDataSource +) : BasePagingPresenter(mainThreadScheduler, dataSourceFactory), + ParentCategoriesPresenter diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/PageableCategoriesDataSource.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/PageableSearchCategoriesDataSource.kt similarity index 86% rename from app/src/main/java/fr/free/nrw/commons/explore/categories/search/PageableCategoriesDataSource.kt rename to app/src/main/java/fr/free/nrw/commons/explore/categories/search/PageableSearchCategoriesDataSource.kt index fd58892fa..bab526cbe 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/PageableCategoriesDataSource.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/PageableSearchCategoriesDataSource.kt @@ -5,12 +5,12 @@ import fr.free.nrw.commons.explore.paging.LiveDataConverter import fr.free.nrw.commons.explore.paging.PageableBaseDataSource import javax.inject.Inject -class PageableCategoriesDataSource @Inject constructor( +class PageableSearchCategoriesDataSource @Inject constructor( liveDataConverter: LiveDataConverter, val categoryClient: CategoryClient ) : PageableBaseDataSource(liveDataConverter) { override val loadFunction = { loadSize: Int, startPosition: Int -> - categoryClient.searchCategories(query, loadSize, startPosition).blockingFirst() + categoryClient.searchCategories(query, loadSize, startPosition).blockingGet() } } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapter.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapter.kt deleted file mode 100644 index fc5dff374..000000000 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapter.kt +++ /dev/null @@ -1,11 +0,0 @@ -package fr.free.nrw.commons.explore.categories.search - -import fr.free.nrw.commons.upload.categories.BaseDelegateAdapter - - -class SearchCategoriesAdapter(onCateoryClicked: (String) -> Unit) : BaseDelegateAdapter( - searchCategoryDelegate( - onCateoryClicked - ), - areItemsTheSame = { oldItem, newItem -> oldItem == newItem } -) diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapterDelegates.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapterDelegates.kt deleted file mode 100644 index 9c7811f27..000000000 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapterDelegates.kt +++ /dev/null @@ -1,15 +0,0 @@ -package fr.free.nrw.commons.explore.categories.search - -import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateLayoutContainer -import fr.free.nrw.commons.R -import fr.free.nrw.commons.category.CATEGORY_PREFIX -import kotlinx.android.synthetic.main.item_recent_searches.* - - -fun searchCategoryDelegate(onCategoryClicked: (String) -> Unit) = - adapterDelegateLayoutContainer(R.layout.item_recent_searches) { - containerView.setOnClickListener { onCategoryClicked(item) } - bind { - textView1.text = item.substringAfter(CATEGORY_PREFIX) - } - } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesFragmentPresenterImpl.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesFragmentPresenterImpl.kt index 691fa961a..998dee1e8 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesFragmentPresenterImpl.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesFragmentPresenterImpl.kt @@ -11,6 +11,6 @@ interface SearchCategoriesFragmentPresenter : PagingContract.Presenter class SearchCategoriesFragmentPresenterImpl @Inject constructor( @Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler, - dataSourceFactory: PageableCategoriesDataSource + dataSourceFactory: PageableSearchCategoriesDataSource ) : BasePagingPresenter(mainThreadScheduler, dataSourceFactory), SearchCategoriesFragmentPresenter diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoryFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoryFragment.kt index adff7d263..042c9d7c4 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoryFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoryFragment.kt @@ -1,27 +1,18 @@ 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 +import fr.free.nrw.commons.explore.categories.PageableCategoryFragment import javax.inject.Inject /** * Displays the category search screen. */ -class SearchCategoryFragment : BasePagingFragment() { +class SearchCategoryFragment : PageableCategoryFragment() { @Inject lateinit var presenter: SearchCategoriesFragmentPresenter - override val errorTextId: Int = R.string.error_loading_categories - override val injectedPresenter get() = presenter - override val pagedListAdapter by lazy { - PagedSearchCategoriesAdapter { - CategoryDetailsActivity.startYourself(context, it) - } - } - override fun getEmptyText(query: String) = getString(R.string.categories_not_found, query) } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/sub/PageableSubCategoriesDataSource.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/sub/PageableSubCategoriesDataSource.kt new file mode 100644 index 000000000..9e5f44966 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/sub/PageableSubCategoriesDataSource.kt @@ -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(liveDataConverter) { + + override val loadFunction = { loadSize: Int, startPosition: Int -> + if (startPosition == 0) { + categoryClient.resetSubCategoryContinuation(query) + } + categoryClient.getSubCategoryList(query).blockingGet() + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/sub/SubCategoriesFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/sub/SubCategoriesFragment.kt new file mode 100644 index 000000000..36ffca70e --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/sub/SubCategoriesFragment.kt @@ -0,0 +1,24 @@ +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.PageableCategoryFragment +import javax.inject.Inject + + +class SubCategoriesFragment : PageableCategoryFragment() { + + @Inject lateinit var presenter: SubCategoriesPresenter + + override val injectedPresenter + 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")!!}") + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/sub/SubCategoriesPresenterImpl.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/sub/SubCategoriesPresenterImpl.kt new file mode 100644 index 000000000..5f41a36a4 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/sub/SubCategoriesPresenterImpl.kt @@ -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 + +class SubCategoriesPresenterImpl @Inject constructor( + @Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler, + dataSourceFactory: PageableSubCategoriesDataSource +) : BasePagingPresenter(mainThreadScheduler, dataSourceFactory), + SubCategoriesPresenter diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/WikidataItemDetailsActivity.java b/app/src/main/java/fr/free/nrw/commons/explore/depictions/WikidataItemDetailsActivity.java index 688d5073c..e061b2dff 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/WikidataItemDetailsActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/WikidataItemDetailsActivity.java @@ -13,6 +13,7 @@ import butterknife.ButterKnife; import com.google.android.material.tabs.TabLayout; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; +import fr.free.nrw.commons.category.CategoryImagesCallback; 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.parent.ParentDepictionsFragment; @@ -26,7 +27,8 @@ import java.util.List; /** * Activity to show depiction media, parent classes and child classes of depicted items in Explore */ -public class WikidataItemDetailsActivity extends NavigationBaseActivity implements MediaDetailPagerFragment.MediaDetailProvider { +public class WikidataItemDetailsActivity extends NavigationBaseActivity implements MediaDetailPagerFragment.MediaDetailProvider, + CategoryImagesCallback { private FragmentManager supportFragmentManager; private DepictedImagesFragment depictionImagesListFragment; private MediaDetailPagerFragment mediaDetailPagerFragment; @@ -73,13 +75,13 @@ public class WikidataItemDetailsActivity extends NavigationBaseActivity implemen * This method is called on success of API call for featured Images. * The viewpager will notified that number of items have changed. */ + @Override public void viewPagerNotifyDataSetChanged() { if (mediaDetailPagerFragment !=null){ mediaDetailPagerFragment.notifyDataSetChanged(); } } - /** * This activity contains 3 tabs and a viewpager. This method is used to set the titles of tab, * Set the fragments according to the tab selected in the viewPager. diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/media/DepictedImagesFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/depictions/media/DepictedImagesFragment.kt index 92936a72d..f31bba68d 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/media/DepictedImagesFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/media/DepictedImagesFragment.kt @@ -17,12 +17,4 @@ class DepictedImagesFragment : PageableMediaFragment() { super.onViewCreated(view, savedInstanceState) onQueryUpdated(arguments!!.getString("entityId")!!) } - - override fun onItemClicked(position: Int) { - (activity as WikidataItemDetailsActivity).onMediaClicked(position) - } - - override fun notifyViewPager() { - (activity as WikidataItemDetailsActivity).viewPagerNotifyDataSetChanged() - } } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/media/PageableMediaFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/media/PageableMediaFragment.kt index 9c960fb24..1c43db691 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/media/PageableMediaFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/media/PageableMediaFragment.kt @@ -1,25 +1,35 @@ package fr.free.nrw.commons.explore.media +import android.content.Context 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.category.CategoryImagesCallback import fr.free.nrw.commons.explore.paging.BasePagingFragment +import fr.free.nrw.commons.media.MediaDetailPagerFragment.MediaDetailProvider import kotlinx.android.synthetic.main.fragment_search_paginated.* -abstract class PageableMediaFragment : BasePagingFragment() { - override val pagedListAdapter by lazy { PagedMediaAdapter(::onItemClicked) } +abstract class PageableMediaFragment : BasePagingFragment(), MediaDetailProvider { + + override val pagedListAdapter by lazy { + PagedMediaAdapter(categoryImagesCallback::onMediaClicked) + } override val errorTextId: Int = R.string.error_loading_images 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?) { super.onViewCreated(view, savedInstanceState) @@ -31,12 +41,12 @@ abstract class PageableMediaFragment : BasePagingFragment() { pagedListAdapter.unregisterAdapterDataObserver(simpleDataObserver) } - fun getMediaAtPosition(position: Int): Media? = + override fun getMediaAtPosition(position: Int): Media? = pagedListAdapter.currentList?.get(position)?.takeIf { it.filename != null } .also { pagedListAdapter.currentList?.loadAround(position) paginatedSearchResultsList.scrollToPosition(position) } - fun getTotalMediaCount(): Int = pagedListAdapter.itemCount + override fun getTotalMediaCount(): Int = pagedListAdapter.itemCount } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragment.kt index d82fe7c83..28709d835 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragment.kt @@ -1,26 +1,15 @@ 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 /** * Displays the image search screen. */ -class SearchMediaFragment : PageableMediaFragment(){ +class SearchMediaFragment : PageableMediaFragment() { @Inject lateinit var presenter: SearchMediaFragmentPresenter override val injectedPresenter get() = presenter - - override fun onItemClicked(position: Int) { - (context as SearchActivity).onSearchImageClicked(position) - } - - override fun notifyViewPager() { - (activity as CategoryImagesCallback).viewPagerNotifyDataSetChanged() - } - } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt index 53f77752c..02b28ff36 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt @@ -2,6 +2,7 @@ package fr.free.nrw.commons.media import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.Media +import fr.free.nrw.commons.category.ContinuationClient import fr.free.nrw.commons.explore.media.MediaConverter import fr.free.nrw.commons.utils.CommonsDateUtil import io.reactivex.Single @@ -24,14 +25,10 @@ class MediaClient @Inject constructor( private val pageMediaInterface: PageMediaInterface, private val mediaDetailInterface: MediaDetailInterface, private val mediaConverter: MediaConverter -) { +) : ContinuationClient() { fun getMediaById(id: String) = - responseToMediaList(mediaInterface.getMediaById(id)).map { it.first() } - - //OkHttpJsonApiClient used JsonKvStore for this. I don't know why. - private val continuationStore: MutableMap?> = mutableMapOf() - private val continuationExists: MutableMap = mutableMapOf() + responseMapper(mediaInterface.getMediaById(id)).map { it.first() } /** * Checks if a page exists on Commons @@ -62,18 +59,8 @@ class MediaClient @Inject constructor( * @return */ fun getMediaListFromCategory(category: String): Single> { - val key = "$CATEGORY_CONTINUATION_PREFIX$category" - return if (hasMorePagesFor(key)) { - responseToMediaList( - mediaInterface.getMediaListFromCategory( - category, - 10, - continuationStore[key] ?: emptyMap() - ), - key - ) - } else { - Single.just(emptyList()) + return continuationRequest(CATEGORY_CONTINUATION_PREFIX, category) { + mediaInterface.getMediaListFromCategory(category, 10, it) } } @@ -86,17 +73,11 @@ class MediaClient @Inject constructor( * @return */ fun getMediaListForUser(userName: String): Single> { - return responseToMediaList( - mediaInterface.getMediaListForUser( - userName, - 10, - continuationStore["user_$userName"] ?: Collections.emptyMap() - ), - "user_$userName" - ) + return continuationRequest("user_", userName) { + mediaInterface.getMediaListForUser(userName, 10, it) + } } - /** * This method takes a keyword as input and returns a list of Media objects filtered using image generator query * It uses the generator query API to get the images searched using a query, 10 at a time. @@ -107,7 +88,7 @@ class MediaClient @Inject constructor( * @return */ fun getMediaListFromSearch(keyword: String?, limit: Int, offset: Int) = - responseToMediaList(mediaInterface.getMediaListFromSearch(keyword, limit, offset)) + responseMapper(mediaInterface.getMediaListFromSearch(keyword, limit, offset)) /** * @return list of images for a particular depict entity @@ -117,7 +98,7 @@ class MediaClient @Inject constructor( srlimit: Int, sroffset: Int ): Single> { - return responseToMediaList( + return responseMapper( mediaInterface.fetchImagesForDepictedItem( "haswbstatement:" + BuildConfig.DEPICTS_PROPERTY + "=" + query, srlimit.toString(), @@ -126,23 +107,6 @@ class MediaClient @Inject constructor( ) } - private fun responseToMediaList( - response: Single, - key: String? = null - ): Single> { - return response.map { - if (key != null) { - continuationExists[key] = - it.continuation()?.let { continuation -> - continuationStore[key] = continuation - true - } ?: false - } - it.query()?.pages() ?: emptyList() - }.flatMap(::mediaFromPageAndEntity) - - } - private fun mediaFromPageAndEntity(pages: List): Single> { return if (pages.isEmpty()) Single.just(emptyList()) @@ -165,7 +129,7 @@ class MediaClient @Inject constructor( * @return */ fun getMedia(titles: String?): Single { - return responseToMediaList(mediaInterface.getMedia(titles)) + return responseMapper(mediaInterface.getMedia(titles)) .map { it.first() } } @@ -176,7 +140,7 @@ class MediaClient @Inject constructor( */ fun getPictureOfTheDay(): Single { val date = CommonsDateUtil.getIso8601DateFormatShort().format(Date()) - return responseToMediaList(mediaInterface.getMediaWithGenerator("Template:Potd/$date")).map { it.first() } + return responseMapper(mediaInterface.getMediaWithGenerator("Template:Potd/$date")).map { it.first() } } @@ -193,23 +157,22 @@ class MediaClient @Inject constructor( } - /** - * Check if media for user has reached the end of the list. - * @param userName - * @return - */ - fun doesMediaListForUserHaveMorePages(userName: String): Boolean { - return hasMorePagesFor("user_$userName") - } - - private fun hasMorePagesFor(key: String) = continuationExists[key] ?: true - fun doesPageContainMedia(title: String?): Single { return pageMediaInterface.getMediaList(title) .map { it.items.isNotEmpty() } } fun resetCategoryContinuation(category: String) { - continuationExists.remove("$CATEGORY_CONTINUATION_PREFIX$category") + resetContinuation(CATEGORY_CONTINUATION_PREFIX, category) + } + + override fun responseMapper( + networkResult: Single, + key: String? + ): Single> { + return networkResult.map { + handleContinuationResponse(it.continuation(), key) + it.query()?.pages() ?: emptyList() + }.flatMap(::mediaFromPageAndEntity) } } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java index 3e5f3f0fd..957f45265 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java @@ -13,7 +13,6 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.Toast; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapter; @@ -26,7 +25,6 @@ import fr.free.nrw.commons.R; import fr.free.nrw.commons.bookmarks.Bookmark; import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider; import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao; -import fr.free.nrw.commons.category.CategoryImagesCallback; import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.utils.DownloadUtils; @@ -269,8 +267,6 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple Timber.d("Returning as activity is destroyed!"); return; } - if (i+1 >= adapter.getCount() && getContext() instanceof CategoryImagesCallback) - ((CategoryImagesCallback) getContext()).requestMoreImages(); getActivity().invalidateOptionsMenu(); } diff --git a/app/src/main/res/layout/fragment_browse_image.xml b/app/src/main/res/layout/fragment_browse_image.xml deleted file mode 100644 index 8a199034e..000000000 --- a/app/src/main/res/layout/fragment_browse_image.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/category/CategoriesModelTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/category/CategoriesModelTest.kt index 80d0be554..4ca38f709 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/category/CategoriesModelTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/category/CategoriesModelTest.kt @@ -4,9 +4,8 @@ import categoryItem import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever import depictedItem -import fr.free.nrw.commons.explore.depictions.DepictsClient import fr.free.nrw.commons.upload.GpsCategoryModel -import io.reactivex.Observable +import io.reactivex.Single import io.reactivex.subjects.BehaviorSubject import org.junit.Before import org.junit.Test @@ -35,7 +34,7 @@ class CategoriesModelTest { val expectedList = listOf("Test") whenever(categoryClient.searchCategoriesForPrefix("tes", 25)) - .thenReturn(Observable.just(expectedList)) + .thenReturn(Single.just(expectedList)) // Checking if both return "Test" val expectedItems = expectedList.map { CategoryItem(it, false) } @@ -56,7 +55,7 @@ class CategoriesModelTest { whenever(gpsCategoryModel.categoriesFromLocation) .thenReturn(BehaviorSubject.createDefault(listOf("gpsCategory"))) whenever(categoryClient.searchCategories("tes", 25)) - .thenReturn(Observable.just(listOf("titleSearch"))) + .thenReturn(Single.just(listOf("titleSearch"))) whenever(categoryDao.recentCategories(25)).thenReturn(listOf("recentCategories")) CategoriesModel(categoryClient, categoryDao, gpsCategoryModel) .searchAll("", listOf("tes"), listOf(depictedItem)) diff --git a/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryClientTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryClientTest.kt index 8870910af..18298a04d 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryClientTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryClientTest.kt @@ -2,11 +2,10 @@ package fr.free.nrw.commons.category import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever -import io.reactivex.Observable +import io.reactivex.Single import org.junit.Before import org.junit.Test -import org.mockito.ArgumentMatchers.anyInt -import org.mockito.ArgumentMatchers.anyString +import org.mockito.ArgumentMatchers.* import org.mockito.InjectMocks import org.mockito.Mock import org.mockito.Mockito.mock @@ -32,7 +31,7 @@ class CategoryClientTest { fun searchCategoriesFound() { val mockResponse = withMockResponse("Category:Test") whenever(categoryInterface.searchCategories(anyString(), anyInt(), anyInt())) - .thenReturn(Observable.just(mockResponse)) + .thenReturn(Single.just(mockResponse)) categoryClient.searchCategories("tes", 10) .test() .assertValues(listOf("Test")) @@ -45,7 +44,7 @@ class CategoryClientTest { fun searchCategoriesNull() { val mockResponse = withNullPages() whenever(categoryInterface.searchCategories(anyString(), anyInt(), anyInt())) - .thenReturn(Observable.just(mockResponse)) + .thenReturn(Single.just(mockResponse)) categoryClient.searchCategories("tes", 10) .test() .assertValues(emptyList()) @@ -58,7 +57,7 @@ class CategoryClientTest { fun searchCategoriesForPrefixFound() { val mockResponse = withMockResponse("Category:Test") whenever(categoryInterface.searchCategoriesForPrefix(anyString(), anyInt(), anyInt())) - .thenReturn(Observable.just(mockResponse)) + .thenReturn(Single.just(mockResponse)) categoryClient.searchCategoriesForPrefix("tes", 10) .test() .assertValues(listOf("Test")) @@ -71,7 +70,7 @@ class CategoryClientTest { fun searchCategoriesForPrefixNull() { val mockResponse = withNullPages() whenever(categoryInterface.searchCategoriesForPrefix(anyString(), anyInt(), anyInt())) - .thenReturn(Observable.just(mockResponse)) + .thenReturn(Single.just(mockResponse)) categoryClient.searchCategoriesForPrefix("tes", 10) .test() .assertValues(emptyList()) @@ -83,8 +82,8 @@ class CategoryClientTest { @Test fun getParentCategoryListFound() { val mockResponse = withMockResponse("Category:Test") - whenever(categoryInterface.getParentCategoryList(anyString())) - .thenReturn(Observable.just(mockResponse)) + whenever(categoryInterface.getParentCategoryList(anyString(), anyMap())) + .thenReturn(Single.just(mockResponse)) categoryClient.getParentCategoryList("tes") .test() .assertValues(listOf("Test")) @@ -93,8 +92,8 @@ class CategoryClientTest { @Test fun getParentCategoryListNull() { val mockResponse = withNullPages() - whenever(categoryInterface.getParentCategoryList(anyString())) - .thenReturn(Observable.just(mockResponse)) + whenever(categoryInterface.getParentCategoryList(anyString(), anyMap())) + .thenReturn(Single.just(mockResponse)) categoryClient.getParentCategoryList("tes") .test() .assertValues(emptyList()) @@ -103,8 +102,8 @@ class CategoryClientTest { @Test fun getSubCategoryListFound() { val mockResponse = withMockResponse("Category:Test") - whenever(categoryInterface.getSubCategoryList("tes")) - .thenReturn(Observable.just(mockResponse)) + whenever(categoryInterface.getSubCategoryList("tes", emptyMap())) + .thenReturn(Single.just(mockResponse)) categoryClient.getSubCategoryList("tes") .test() .assertValues(listOf("Test")) @@ -113,8 +112,11 @@ class CategoryClientTest { @Test fun getSubCategoryListNull() { val mockResponse = withNullPages() - whenever(categoryInterface.getSubCategoryList(anyString())) - .thenReturn(Observable.just(mockResponse)) + whenever(categoryInterface.getSubCategoryList( + anyString(), + anyMap() + )) + .thenReturn(Single.just(mockResponse)) categoryClient.getSubCategoryList("tes") .test() .assertValues(emptyList()) diff --git a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt index 365c0ae7f..6c853c375 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt @@ -1,7 +1,9 @@ package fr.free.nrw.commons.contributions import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import com.nhaarman.mockitokotlin2.* +import com.nhaarman.mockitokotlin2.verify +import com.nhaarman.mockitokotlin2.verifyZeroInteractions +import com.nhaarman.mockitokotlin2.whenever import fr.free.nrw.commons.Media import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.media.MediaClient @@ -58,8 +60,6 @@ class ContributionBoundaryCallbackTest { whenever(mediaClient.getMediaListForUser(anyString())).thenReturn( Single.just(listOf(mock(Media::class.java))) ) - whenever(mediaClient.doesMediaListForUserHaveMorePages(anyString())) - .thenReturn(true) contributionBoundaryCallback.onZeroItemsLoaded() verify(repository).save(anyList()); verify(mediaClient).getMediaListForUser(anyString()); @@ -73,8 +73,6 @@ class ContributionBoundaryCallbackTest { whenever(mediaClient.getMediaListForUser(anyString())).thenReturn( Single.just(listOf(mock(Media::class.java))) ) - whenever(mediaClient.doesMediaListForUserHaveMorePages(anyString())) - .thenReturn(true) contributionBoundaryCallback.onItemAtEndLoaded(mock(Contribution::class.java)) verify(repository).save(anyList()); verify(mediaClient).getMediaListForUser(anyString()); @@ -88,8 +86,6 @@ class ContributionBoundaryCallbackTest { whenever(mediaClient.getMediaListForUser(anyString())).thenReturn( Single.just(listOf(mock(Media::class.java))) ) - whenever(mediaClient.doesMediaListForUserHaveMorePages(anyString())) - .thenReturn(true) contributionBoundaryCallback.onItemAtFrontLoaded(mock(Contribution::class.java)) verify(repository).save(anyList()); verify(mediaClient).getMediaListForUser(anyString()); @@ -103,28 +99,14 @@ class ContributionBoundaryCallbackTest { whenever(mediaClient.getMediaListForUser(anyString())).thenReturn( Single.just(listOf(mock(Media::class.java))) ) - whenever(mediaClient.doesMediaListForUserHaveMorePages(anyString())) - .thenReturn(true) contributionBoundaryCallback.fetchContributions() verify(repository).save(anyList()); verify(mediaClient).getMediaListForUser(anyString()); } - @Test - fun testFetchContributionsForEndOfList() { - whenever(sessionManager.userName).thenReturn("Test") - whenever(mediaClient.doesMediaListForUserHaveMorePages(anyString())) - .thenReturn(false) - contributionBoundaryCallback.fetchContributions() - verify(mediaClient, times(0)).getMediaListForUser(anyString()) - verifyNoMoreInteractions(repository) - } - @Test fun testFetchContributionsFailed() { whenever(sessionManager.userName).thenReturn("Test") - whenever(mediaClient.doesMediaListForUserHaveMorePages(anyString())) - .thenReturn(true) whenever(mediaClient.getMediaListForUser(anyString())).thenReturn(Single.error(Exception("Error"))) contributionBoundaryCallback.fetchContributions() verifyZeroInteractions(repository); diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/categories/parent/PageableParentCategoriesDataSourceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/categories/parent/PageableParentCategoriesDataSourceTest.kt new file mode 100644 index 000000000..ca7b85de6 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/categories/parent/PageableParentCategoriesDataSourceTest.kt @@ -0,0 +1,48 @@ +package fr.free.nrw.commons.explore.categories.parent + +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 PageableParentCategoriesDataSourceTest{ + @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 = + PageableParentCategoriesDataSource(liveDataConverter, categoryClient) + dataSource.onQueryUpdated("test") + whenever(categoryClient.getParentCategoryList("test")) + .thenReturn(Single.just(emptyList())) + assertThat(dataSource.loadFunction(-1, 0), `is`(emptyList())) + verify(categoryClient).resetParentCategoryContinuation("test") + } + + @Test + fun `loadFunction does not call reset at any other position`() { + val dataSource = + PageableParentCategoriesDataSource(liveDataConverter, categoryClient) + dataSource.onQueryUpdated("test") + whenever(categoryClient.getParentCategoryList("test")) + .thenReturn(Single.just(emptyList())) + assertThat(dataSource.loadFunction(-1, 1), `is`(emptyList())) + verify(categoryClient, never()).resetParentCategoryContinuation("test") + } +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/categories/sub/PageableSubCategoriesDataSourceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/categories/sub/PageableSubCategoriesDataSourceTest.kt new file mode 100644 index 000000000..2fa52a221 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/categories/sub/PageableSubCategoriesDataSourceTest.kt @@ -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") + } +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/categroies/PageableCategoriesDataSourceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/categroies/PageableSearchCategoriesDataSourceTest.kt similarity index 65% rename from app/src/test/kotlin/fr/free/nrw/commons/explore/categroies/PageableCategoriesDataSourceTest.kt rename to app/src/test/kotlin/fr/free/nrw/commons/explore/categroies/PageableSearchCategoriesDataSourceTest.kt index 5a3cff5fe..85ae84def 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/explore/categroies/PageableCategoriesDataSourceTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/categroies/PageableSearchCategoriesDataSourceTest.kt @@ -3,19 +3,20 @@ package fr.free.nrw.commons.explore.categroies import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever import fr.free.nrw.commons.category.CategoryClient -import fr.free.nrw.commons.explore.categories.search.PageableCategoriesDataSource -import io.reactivex.Observable +import fr.free.nrw.commons.explore.categories.search.PageableSearchCategoriesDataSource +import io.reactivex.Single import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers import org.junit.Test -class PageableCategoriesDataSourceTest { +class PageableSearchCategoriesDataSourceTest { @Test fun `loadFunction loads categories`() { val categoryClient: CategoryClient = mock() whenever(categoryClient.searchCategories("test", 0, 1)) - .thenReturn(Observable.just(emptyList())) - val pageableCategoriesDataSource = PageableCategoriesDataSource(mock(), categoryClient) + .thenReturn(Single.just(emptyList())) + val pageableCategoriesDataSource = + PageableSearchCategoriesDataSource(mock(), categoryClient) pageableCategoriesDataSource.onQueryUpdated("test") assertThat(pageableCategoriesDataSource.loadFunction(0, 1), Matchers.`is`(emptyList())) }