From 7817518462b8d1071d602946acb8519112ac3eaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Mac=20Gillicuddy?= Date: Thu, 25 Jun 2020 10:38:58 +0100 Subject: [PATCH] #3820 Convert CategoryImagesListFragment to use Pagination (#3821) --- .../category/CategoryDetailsActivity.java | 44 +-- .../category/CategoryImagesActivity.java | 27 +- .../category/CategoryImagesListFragment.java | 266 ------------------ .../category/SubCategoryListFragment.java | 2 +- .../di/CommonsApplicationComponent.java | 8 +- .../nrw/commons/di/FragmentBuilderModule.java | 10 +- .../nrw/commons/explore/ExploreActivity.java | 36 ++- .../nrw/commons/explore/SearchActivity.java | 6 +- .../free/nrw/commons/explore/SearchModule.kt | 4 +- .../explore/categories/CategoriesModule.kt | 15 + .../media/CategoriesMediaFragment.kt | 31 ++ .../media/CategoryMediaPresenterImpl.kt | 20 ++ .../PageableCategoriesMediaDataSource.kt | 20 ++ .../PageableCategoriesDataSource.kt | 2 +- .../PagedSearchCategoriesAdapter.kt | 2 +- .../{ => search}/SearchCategoriesAdapter.kt | 6 +- .../SearchCategoriesAdapterDelegates.kt | 2 +- .../SearchCategoriesFragmentPresenterImpl.kt | 2 +- .../{ => search}/SearchCategoryFragment.kt | 7 +- .../WikidataItemDetailsActivity.java | 4 +- .../commons/explore/media/MediaConverter.kt | 9 +- .../explore/media/PageableMediaFragment.kt | 4 +- .../media/SearchMediaFragmentPresenterImpl.kt | 2 +- .../fr/free/nrw/commons/media/MediaClient.kt | 37 ++- .../res/layout/fragment_category_images.xml | 41 --- .../PageableCategoriesMediaDataSourceTest.kt | 49 ++++ .../PageableCategoriesDataSourceTest.kt | 2 +- .../PageableChildDepictionsDataSourceTest.kt | 1 + .../free/nrw/commons/media/MediaClientTest.kt | 4 +- 29 files changed, 245 insertions(+), 418 deletions(-) delete mode 100644 app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java create mode 100644 app/src/main/java/fr/free/nrw/commons/explore/categories/CategoriesModule.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/explore/categories/media/CategoriesMediaFragment.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/explore/categories/media/CategoryMediaPresenterImpl.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/explore/categories/media/PageableCategoriesMediaDataSource.kt rename app/src/main/java/fr/free/nrw/commons/explore/categories/{ => search}/PageableCategoriesDataSource.kt (91%) rename app/src/main/java/fr/free/nrw/commons/explore/categories/{ => search}/PagedSearchCategoriesAdapter.kt (96%) rename app/src/main/java/fr/free/nrw/commons/explore/categories/{ => search}/SearchCategoriesAdapter.kt (67%) rename app/src/main/java/fr/free/nrw/commons/explore/categories/{ => search}/SearchCategoriesAdapterDelegates.kt (90%) rename app/src/main/java/fr/free/nrw/commons/explore/categories/{ => search}/SearchCategoriesFragmentPresenterImpl.kt (92%) rename app/src/main/java/fr/free/nrw/commons/explore/categories/{ => search}/SearchCategoryFragment.kt (79%) delete mode 100644 app/src/main/res/layout/fragment_category_images.xml create mode 100644 app/src/test/kotlin/fr/free/nrw/commons/explore/categories/media/PageableCategoriesMediaDataSourceTest.kt 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 597acc18a..02af44c49 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 @@ -8,26 +8,22 @@ 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; import androidx.viewpager.widget.ViewPager; - -import com.google.android.material.tabs.TabLayout; - -import java.util.ArrayList; -import java.util.List; - import butterknife.BindView; 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.Utils; import fr.free.nrw.commons.explore.ViewPagerAdapter; +import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment; import fr.free.nrw.commons.media.MediaDetailPagerFragment; import fr.free.nrw.commons.theme.NavigationBaseActivity; +import java.util.ArrayList; +import java.util.List; /** * This activity displays details of a particular category @@ -36,12 +32,11 @@ import fr.free.nrw.commons.theme.NavigationBaseActivity; */ public class CategoryDetailsActivity extends NavigationBaseActivity - implements MediaDetailPagerFragment.MediaDetailProvider, - AdapterView.OnItemClickListener, CategoryImagesCallback { + implements MediaDetailPagerFragment.MediaDetailProvider, CategoryImagesCallback { private FragmentManager supportFragmentManager; - private CategoryImagesListFragment categoryImagesListFragment; + private CategoriesMediaFragment categoriesMediaFragment; private MediaDetailPagerFragment mediaDetails; private String categoryName; @BindView(R.id.mediaContainer) FrameLayout mediaContainer; @@ -73,7 +68,7 @@ public class CategoryDetailsActivity extends NavigationBaseActivity private void setTabs() { List fragmentList = new ArrayList<>(); List titleList = new ArrayList<>(); - categoryImagesListFragment = new CategoryImagesListFragment(); + categoriesMediaFragment = new CategoriesMediaFragment(); SubCategoryListFragment subCategoryListFragment = new SubCategoryListFragment(); SubCategoryListFragment parentCategoryListFragment = new SubCategoryListFragment(); categoryName = getIntent().getStringExtra("categoryName"); @@ -81,14 +76,14 @@ public class CategoryDetailsActivity extends NavigationBaseActivity Bundle arguments = new Bundle(); arguments.putString("categoryName", categoryName); arguments.putBoolean("isParentCategory", false); - categoryImagesListFragment.setArguments(arguments); + categoriesMediaFragment.setArguments(arguments); subCategoryListFragment.setArguments(arguments); Bundle parentCategoryArguments = new Bundle(); parentCategoryArguments.putString("categoryName", categoryName); parentCategoryArguments.putBoolean("isParentCategory", true); parentCategoryListFragment.setArguments(parentCategoryArguments); } - fragmentList.add(categoryImagesListFragment); + fragmentList.add(categoriesMediaFragment); titleList.add("MEDIA"); fragmentList.add(subCategoryListFragment); titleList.add("SUBCATEGORIES"); @@ -111,8 +106,7 @@ public class CategoryDetailsActivity extends NavigationBaseActivity /** * This method is called onClick of media inside category details (CategoryImageListFragment). */ - @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); @@ -127,7 +121,7 @@ public class CategoryDetailsActivity extends NavigationBaseActivity .commit(); supportFragmentManager.executePendingTransactions(); } - mediaDetails.showImage(i); + mediaDetails.showImage(position); forceInitBackButton(); } @@ -152,12 +146,7 @@ public class CategoryDetailsActivity extends NavigationBaseActivity */ @Override public Media getMediaAtPosition(int i) { - if (categoryImagesListFragment.getAdapter() == null) { - // not yet ready to return data - return null; - } else { - return (Media) categoryImagesListFragment.getAdapter().getItem(i); - } + return categoriesMediaFragment.getMediaAtPosition(i); } /** @@ -167,10 +156,7 @@ public class CategoryDetailsActivity extends NavigationBaseActivity */ @Override public int getTotalMediaCount() { - if (categoryImagesListFragment.getAdapter() == null) { - return 0; - } - return categoryImagesListFragment.getAdapter().getCount(); + return categoriesMediaFragment.getTotalMediaCount(); } /** @@ -232,8 +218,6 @@ public class CategoryDetailsActivity extends NavigationBaseActivity */ @Override public void requestMoreImages() { - if (categoryImagesListFragment!=null){ - categoryImagesListFragment.fetchMoreImagesViewPager(); - } + //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 aa2c87f38..c7c59ad3d 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 @@ -8,14 +8,13 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; - import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; - import butterknife.ButterKnife; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; import fr.free.nrw.commons.explore.SearchActivity; +import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment; import fr.free.nrw.commons.media.MediaDetailPagerFragment; import fr.free.nrw.commons.theme.NavigationBaseActivity; @@ -34,7 +33,7 @@ public class CategoryImagesActivity private FragmentManager supportFragmentManager; - private CategoryImagesListFragment categoryImagesListFragment; + private CategoriesMediaFragment categoriesMediaFragment; private MediaDetailPagerFragment mediaDetails; /** @@ -66,15 +65,15 @@ public class CategoryImagesActivity * Gets the categoryName from the intent and initializes the fragment for showing images of that category */ private void setCategoryImagesFragment() { - categoryImagesListFragment = new CategoryImagesListFragment(); + categoriesMediaFragment = new CategoriesMediaFragment(); String categoryName = getIntent().getStringExtra("categoryName"); if (getIntent() != null && categoryName != null) { Bundle arguments = new Bundle(); arguments.putString("categoryName", categoryName); - categoryImagesListFragment.setArguments(arguments); + categoriesMediaFragment.setArguments(arguments); FragmentTransaction transaction = supportFragmentManager.beginTransaction(); transaction - .add(R.id.fragmentContainer, categoryImagesListFragment) + .add(R.id.fragmentContainer, categoriesMediaFragment) .commit(); } } @@ -137,12 +136,7 @@ public class CategoryImagesActivity */ @Override public Media getMediaAtPosition(int i) { - if (categoryImagesListFragment.getAdapter() == null) { - // not yet ready to return data - return null; - } else { - return (Media) categoryImagesListFragment.getAdapter().getItem(i); - } + return categoriesMediaFragment.getMediaAtPosition(i); } /** @@ -163,10 +157,7 @@ public class CategoryImagesActivity */ @Override public int getTotalMediaCount() { - if (categoryImagesListFragment.getAdapter() == null) { - return 0; - } - return categoryImagesListFragment.getAdapter().getCount(); + return categoriesMediaFragment.getTotalMediaCount(); } /** @@ -202,8 +193,6 @@ public class CategoryImagesActivity */ @Override public void requestMoreImages() { - if (categoryImagesListFragment!=null){ - categoryImagesListFragment.fetchMoreImagesViewPager(); - } + //unneeded } } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java deleted file mode 100644 index a7faab005..000000000 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java +++ /dev/null @@ -1,266 +0,0 @@ -package fr.free.nrw.commons.category; - -import static android.view.View.GONE; -import static android.view.View.VISIBLE; - -import android.annotation.SuppressLint; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.GridView; -import android.widget.ListAdapter; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.TextView; -import androidx.annotation.Nullable; -import butterknife.BindView; -import butterknife.ButterKnife; -import dagger.android.support.DaggerFragment; -import fr.free.nrw.commons.Media; -import fr.free.nrw.commons.R; -import fr.free.nrw.commons.kvstore.JsonKvStore; -import fr.free.nrw.commons.media.MediaClient; -import fr.free.nrw.commons.utils.NetworkUtils; -import fr.free.nrw.commons.utils.ViewUtil; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.schedulers.Schedulers; -import java.util.List; -import javax.inject.Inject; -import javax.inject.Named; -import timber.log.Timber; - -/** - * Displays images for a particular category with load more on scrolling incorporated - */ -public class CategoryImagesListFragment extends DaggerFragment { - - /** - * counts the total number of items loaded from the API - */ - private int mediaSize = 0; - - private GridViewAdapter gridAdapter; - - @BindView(R.id.statusMessage) - TextView statusTextView; - @BindView(R.id.loadingImagesProgressBar) ProgressBar progressBar; - @BindView(R.id.categoryImagesList) GridView gridView; - @BindView(R.id.parentLayout) RelativeLayout parentLayout; - private CompositeDisposable compositeDisposable = new CompositeDisposable(); - private boolean hasMoreImages = true; - private boolean isLoading = true; - private String categoryName = null; - - @Inject MediaClient mediaClient; - @Inject - @Named("default_preferences") - JsonKvStore categoryKvStore; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_category_images, container, false); - ButterKnife.bind(this, v); - return v; - } - - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - gridView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity()); - initViews(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - compositeDisposable.clear(); - } - - /** - * Initializes the UI elements for the fragment - * Setup the grid view to and scroll listener for it - */ - private void initViews() { - String categoryName = getArguments().getString("categoryName"); - if (getArguments() != null && categoryName != null) { - this.categoryName = categoryName; - resetQueryContinueValues(categoryName); - initList(); - setScrollListener(); - } - } - - /** - * Query continue values determine the last page that was loaded for the particular keyword - * This method resets those values, so that the results can be queried from the first page itself - * @param keyword - */ - private void resetQueryContinueValues(String keyword) { - categoryKvStore.remove("query_continue_" + keyword); - } - - /** - * Checks for internet connection and then initializes the grid view with first 10 images of that category - */ - @SuppressLint("CheckResult") - private void initList() { - if (!NetworkUtils.isInternetConnectionEstablished(getContext())) { - handleNoInternet(); - return; - } - - isLoading = true; - progressBar.setVisibility(VISIBLE); - compositeDisposable.add(mediaClient.getMediaListFromCategory(categoryName) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::handleSuccess, this::handleError)); - } - - /** - * Handles the UI updates for no internet scenario - */ - private void handleNoInternet() { - progressBar.setVisibility(GONE); - if (gridAdapter == null || gridAdapter.isEmpty()) { - statusTextView.setVisibility(VISIBLE); - statusTextView.setText(getString(R.string.no_internet)); - } else { - ViewUtil.showShortSnackbar(parentLayout, R.string.no_internet); - } - } - - /** - * Logs and handles API error scenario - * @param throwable - */ - private void handleError(Throwable throwable) { - Timber.e(throwable, "Error occurred while loading images inside a category"); - try{ - ViewUtil.showShortSnackbar(parentLayout, R.string.error_loading_images); - initErrorView(); - }catch (Exception e){ - e.printStackTrace(); - } - - } - - /** - * Handles the UI updates for a error scenario - */ - private void initErrorView() { - progressBar.setVisibility(GONE); - if (gridAdapter == null || gridAdapter.isEmpty()) { - statusTextView.setVisibility(VISIBLE); - statusTextView.setText(getString(R.string.no_images_found)); - } else { - statusTextView.setVisibility(GONE); - } - } - - /** - * Initializes the adapter with a list of Media objects - * @param mediaList List of new Media to be displayed - */ - private void setAdapter(List mediaList) { - gridAdapter = new GridViewAdapter(this.getContext(), R.layout.layout_category_images, mediaList); - gridView.setAdapter(gridAdapter); - } - - /** - * Sets the scroll listener for the grid view so that more images are fetched when the user scrolls down - * Checks if the category has more images before loading - * Also checks whether images are currently being fetched before triggering another request - */ - private void setScrollListener() { - gridView.setOnScrollListener(new AbsListView.OnScrollListener() { - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - } - - @Override - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - if (hasMoreImages && !isLoading && (firstVisibleItem + visibleItemCount + 1 >= totalItemCount)) { - isLoading = true; - fetchMoreImages(); - } - if (!hasMoreImages){ - progressBar.setVisibility(GONE); - } - } - }); - } - - /** - * This method is called when viewPager has reached its end. - * Fetches more images for the category and adds it to the grid view and viewpager adapter - */ - public void fetchMoreImagesViewPager(){ - if (hasMoreImages && !isLoading) { - isLoading = true; - fetchMoreImages(); - } - if (!hasMoreImages){ - progressBar.setVisibility(GONE); - } - } - - /** - * Fetches more images for the category and adds it to the grid view adapter - */ - @SuppressLint("CheckResult") - private void fetchMoreImages() { - if (!NetworkUtils.isInternetConnectionEstablished(getContext())) { - handleNoInternet(); - return; - } - - progressBar.setVisibility(VISIBLE); - compositeDisposable.add(mediaClient.getMediaListFromCategory(categoryName) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::handleSuccess, this::handleError)); - } - - /** - * Handles the success scenario - * On first load, it initializes the grid view. On subsequent loads, it adds items to the adapter - * @param collection List of new Media to be displayed - */ - private void handleSuccess(List collection) { - if (collection == null || collection.isEmpty()) { - initErrorView(); - hasMoreImages = false; - return; - } - - if (gridAdapter == null) { - setAdapter(collection); - } else { - if (gridAdapter.containsAll(collection)) { - hasMoreImages = false; - return; - } - gridAdapter.addItems(collection); - ((CategoryImagesCallback) getContext()).viewPagerNotifyDataSetChanged(); - } - - progressBar.setVisibility(GONE); - isLoading = false; - statusTextView.setVisibility(GONE); - } - - /** - * It return an instance of gridView adapter which helps in extracting media details - * used by the gridView - * @return GridView Adapter - */ - public ListAdapter getAdapter() { - return gridAdapter; - } - -} 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 index bc884d535..d5f33a20f 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/category/SubCategoryListFragment.java @@ -20,7 +20,7 @@ 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.SearchCategoriesAdapter; +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; diff --git a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java index 4153f5c86..7fc66e507 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java +++ b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java @@ -2,6 +2,7 @@ package fr.free.nrw.commons.di; import com.google.gson.Gson; +import fr.free.nrw.commons.explore.categories.CategoriesModule; import javax.inject.Singleton; import dagger.Component; @@ -33,7 +34,12 @@ import fr.free.nrw.commons.widget.PicOfDayAppWidget; ActivityBuilderModule.class, FragmentBuilderModule.class, ServiceBuilderModule.class, - ContentProviderBuilderModule.class, UploadModule.class, ContributionsModule.class, SearchModule.class, DepictionModule.class + ContentProviderBuilderModule.class, + UploadModule.class, + ContributionsModule.class, + SearchModule.class, + DepictionModule.class, + CategoriesModule.class }) public interface CommonsApplicationComponent extends AndroidInjector { void inject(CommonsApplication application); 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 89620306f..ff0526da1 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,14 @@ 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.CategoryImagesListFragment; 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.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.SearchCategoryFragment; +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; @@ -46,9 +46,6 @@ public abstract class FragmentBuilderModule { @ContributesAndroidInjector abstract SettingsFragment bindSettingsFragment(); - @ContributesAndroidInjector - abstract CategoryImagesListFragment bindFeaturedImagesListFragment(); - @ContributesAndroidInjector abstract DepictedImagesFragment bindDepictedImagesFragment(); @@ -99,4 +96,7 @@ public abstract class FragmentBuilderModule { @ContributesAndroidInjector abstract ChildDepictionsFragment bindChildDepictionsFragment(); + + @ContributesAndroidInjector + abstract CategoriesMediaFragment bindCategoriesMediaFragment(); } 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 dcdb6a5cb..4140b248e 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 @@ -18,7 +18,7 @@ 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.category.CategoryImagesListFragment; +import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment; import fr.free.nrw.commons.media.MediaDetailPagerFragment; import fr.free.nrw.commons.theme.NavigationBaseActivity; import java.util.ArrayList; @@ -34,8 +34,8 @@ public class ExploreActivity implements MediaDetailPagerFragment.MediaDetailProvider, AdapterView.OnItemClickListener, CategoryImagesCallback { - private static final String FEATURED_IMAGES_CATEGORY = "Category:Featured_pictures_on_Wikimedia_Commons"; - private static final String MOBILE_UPLOADS_CATEGORY = "Category:Uploaded_with_Mobile/Android"; + private static final String FEATURED_IMAGES_CATEGORY = "Featured_pictures_on_Wikimedia_Commons"; + private static final String MOBILE_UPLOADS_CATEGORY = "Uploaded_with_Mobile/Android"; @BindView(R.id.mediaContainer) @@ -47,8 +47,8 @@ public class ExploreActivity ViewPagerAdapter viewPagerAdapter; private FragmentManager supportFragmentManager; private MediaDetailPagerFragment mediaDetails; - private CategoryImagesListFragment mobileImagesListFragment; - private CategoryImagesListFragment featuredImagesListFragment; + private CategoriesMediaFragment mobileImagesListFragment; + private CategoriesMediaFragment featuredImagesListFragment; /** * Consumers should be simply using this method to use this activity. @@ -83,14 +83,14 @@ public class ExploreActivity List fragmentList = new ArrayList<>(); List titleList = new ArrayList<>(); - featuredImagesListFragment = new CategoryImagesListFragment(); + featuredImagesListFragment = new CategoriesMediaFragment(); Bundle featuredArguments = new Bundle(); featuredArguments.putString("categoryName", FEATURED_IMAGES_CATEGORY); featuredImagesListFragment.setArguments(featuredArguments); fragmentList.add(featuredImagesListFragment); titleList.add(getString(R.string.explore_tab_title_featured).toUpperCase()); - mobileImagesListFragment = new CategoryImagesListFragment(); + mobileImagesListFragment = new CategoriesMediaFragment(); Bundle mobileArguments = new Bundle(); mobileArguments.putString("categoryName", MOBILE_UPLOADS_CATEGORY); mobileImagesListFragment.setArguments(mobileArguments); @@ -110,10 +110,10 @@ public class ExploreActivity */ @Override public Media getMediaAtPosition(int i) { - if (mobileImagesListFragment.getAdapter() != null && tabLayout.getSelectedTabPosition() == 1) { - return (Media) mobileImagesListFragment.getAdapter().getItem(i); - } else if (featuredImagesListFragment.getAdapter() != null && tabLayout.getSelectedTabPosition() == 0) { - return (Media) featuredImagesListFragment.getAdapter().getItem(i); + if (tabLayout.getSelectedTabPosition() == 1) { + return mobileImagesListFragment.getMediaAtPosition(i); + } else if (tabLayout.getSelectedTabPosition() == 0) { + return featuredImagesListFragment.getMediaAtPosition(i); } else { return null; } @@ -127,10 +127,10 @@ public class ExploreActivity */ @Override public int getTotalMediaCount() { - if (mobileImagesListFragment.getAdapter() != null && tabLayout.getSelectedTabPosition() == 1) { - return mobileImagesListFragment.getAdapter().getCount(); - } else if (featuredImagesListFragment.getAdapter() != null && tabLayout.getSelectedTabPosition() == 0) { - return featuredImagesListFragment.getAdapter().getCount(); + if (tabLayout.getSelectedTabPosition() == 1) { + return mobileImagesListFragment.getTotalMediaCount(); + } else if (tabLayout.getSelectedTabPosition() == 0) { + return featuredImagesListFragment.getTotalMediaCount(); } else { return 0; } @@ -170,11 +170,7 @@ public class ExploreActivity */ @Override public void requestMoreImages() { - if (mobileImagesListFragment != null && tabLayout.getSelectedTabPosition() == 1) { - mobileImagesListFragment.fetchMoreImagesViewPager(); - } else if (featuredImagesListFragment != null && tabLayout.getSelectedTabPosition() == 0) { - featuredImagesListFragment.fetchMoreImagesViewPager(); - } + //unneeded } /** 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 e7c016bfe..1264d87b3 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 @@ -19,7 +19,7 @@ import com.jakewharton.rxbinding2.widget.RxSearchView; 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.categories.SearchCategoryFragment; +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.RecentSearch; @@ -165,7 +165,7 @@ public class SearchActivity extends NavigationBaseActivity */ @Override public Media getMediaAtPosition(int i) { - return searchMediaFragment.getImageAtPosition(i); + return searchMediaFragment.getMediaAtPosition(i); } /** @@ -173,7 +173,7 @@ public class SearchActivity extends NavigationBaseActivity */ @Override public int getTotalMediaCount() { - return searchMediaFragment.getTotalImagesCount(); + return searchMediaFragment.getTotalMediaCount(); } /** diff --git a/app/src/main/java/fr/free/nrw/commons/explore/SearchModule.kt b/app/src/main/java/fr/free/nrw/commons/explore/SearchModule.kt index 40a3c32ef..e0a9d41a0 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/SearchModule.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/SearchModule.kt @@ -2,8 +2,8 @@ package fr.free.nrw.commons.explore import dagger.Binds import dagger.Module -import fr.free.nrw.commons.explore.categories.SearchCategoriesFragmentPresenter -import fr.free.nrw.commons.explore.categories.SearchCategoriesFragmentPresenterImpl +import fr.free.nrw.commons.explore.categories.search.SearchCategoriesFragmentPresenter +import fr.free.nrw.commons.explore.categories.search.SearchCategoriesFragmentPresenterImpl import fr.free.nrw.commons.explore.depictions.search.SearchDepictionsFragmentPresenter import fr.free.nrw.commons.explore.depictions.search.SearchDepictionsFragmentPresenterImpl import fr.free.nrw.commons.explore.media.SearchMediaFragmentPresenter 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 new file mode 100644 index 000000000..1022c4ad4 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/CategoriesModule.kt @@ -0,0 +1,15 @@ +package fr.free.nrw.commons.explore.categories + +import dagger.Binds +import dagger.Module +import fr.free.nrw.commons.explore.categories.media.CategoryMediaPresenter +import fr.free.nrw.commons.explore.categories.media.CategoryMediaPresenterImpl + + +@Module +abstract class CategoriesModule { + + @Binds + abstract fun CategoryMediaPresenterImpl.bindsParentDepictionPresenter() + : CategoryMediaPresenter +} 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 new file mode 100644 index 000000000..9347c90d8 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/media/CategoriesMediaFragment.kt @@ -0,0 +1,31 @@ +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 + + +class CategoriesMediaFragment : PageableMediaFragment() { + @Inject + lateinit var presenter: CategoryMediaPresenter + + override val injectedPresenter + get() = presenter + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + 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/media/CategoryMediaPresenterImpl.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/media/CategoryMediaPresenterImpl.kt new file mode 100644 index 000000000..0ca581416 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/media/CategoryMediaPresenterImpl.kt @@ -0,0 +1,20 @@ +package fr.free.nrw.commons.explore.categories.media + +import fr.free.nrw.commons.Media +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 CategoryMediaPresenter : PagingContract.Presenter + +/** + * Presenter for DepictedImagesFragment + */ +class CategoryMediaPresenterImpl @Inject constructor( + @Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler, + dataSourceFactory: PageableCategoriesMediaDataSource +) : BasePagingPresenter(mainThreadScheduler, dataSourceFactory), + CategoryMediaPresenter diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/media/PageableCategoriesMediaDataSource.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/media/PageableCategoriesMediaDataSource.kt new file mode 100644 index 000000000..7ba5209f8 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/media/PageableCategoriesMediaDataSource.kt @@ -0,0 +1,20 @@ +package fr.free.nrw.commons.explore.categories.media + +import fr.free.nrw.commons.Media +import fr.free.nrw.commons.explore.depictions.search.LoadFunction +import fr.free.nrw.commons.explore.paging.LiveDataConverter +import fr.free.nrw.commons.explore.paging.PageableBaseDataSource +import fr.free.nrw.commons.media.MediaClient +import javax.inject.Inject + +class PageableCategoriesMediaDataSource @Inject constructor( + liveDataConverter: LiveDataConverter, + private val mediaClient: MediaClient +) : PageableBaseDataSource(liveDataConverter) { + override val loadFunction: LoadFunction = { loadSize: Int, startPosition: Int -> + if(startPosition == 0){ + mediaClient.resetCategoryContinuation(query) + } + mediaClient.getMediaListFromCategory(query).blockingGet() + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/PageableCategoriesDataSource.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/PageableCategoriesDataSource.kt similarity index 91% rename from app/src/main/java/fr/free/nrw/commons/explore/categories/PageableCategoriesDataSource.kt rename to app/src/main/java/fr/free/nrw/commons/explore/categories/search/PageableCategoriesDataSource.kt index aa558b388..fd58892fa 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/PageableCategoriesDataSource.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/PageableCategoriesDataSource.kt @@ -1,4 +1,4 @@ -package fr.free.nrw.commons.explore.categories +package fr.free.nrw.commons.explore.categories.search import fr.free.nrw.commons.category.CategoryClient import fr.free.nrw.commons.explore.paging.LiveDataConverter diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/PagedSearchCategoriesAdapter.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/PagedSearchCategoriesAdapter.kt similarity index 96% rename from app/src/main/java/fr/free/nrw/commons/explore/categories/PagedSearchCategoriesAdapter.kt rename to app/src/main/java/fr/free/nrw/commons/explore/categories/search/PagedSearchCategoriesAdapter.kt index fd41a6b73..220339180 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/PagedSearchCategoriesAdapter.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/PagedSearchCategoriesAdapter.kt @@ -1,4 +1,4 @@ -package fr.free.nrw.commons.explore.categories +package fr.free.nrw.commons.explore.categories.search import android.view.View import android.view.ViewGroup diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapter.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapter.kt similarity index 67% rename from app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapter.kt rename to app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapter.kt index 6e7bae236..fc5dff374 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapter.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapter.kt @@ -1,9 +1,11 @@ -package fr.free.nrw.commons.explore.categories +package fr.free.nrw.commons.explore.categories.search import fr.free.nrw.commons.upload.categories.BaseDelegateAdapter class SearchCategoriesAdapter(onCateoryClicked: (String) -> Unit) : BaseDelegateAdapter( - searchCategoryDelegate(onCateoryClicked), + searchCategoryDelegate( + onCateoryClicked + ), areItemsTheSame = { oldItem, newItem -> oldItem == newItem } ) diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterDelegates.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapterDelegates.kt similarity index 90% rename from app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterDelegates.kt rename to app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapterDelegates.kt index 6cd3a3386..9c7811f27 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesAdapterDelegates.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesAdapterDelegates.kt @@ -1,4 +1,4 @@ -package fr.free.nrw.commons.explore.categories +package fr.free.nrw.commons.explore.categories.search import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateLayoutContainer import fr.free.nrw.commons.R diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesFragmentPresenterImpl.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesFragmentPresenterImpl.kt similarity index 92% rename from app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesFragmentPresenterImpl.kt rename to app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesFragmentPresenterImpl.kt index de6234791..691fa961a 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesFragmentPresenterImpl.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoriesFragmentPresenterImpl.kt @@ -1,4 +1,4 @@ -package fr.free.nrw.commons.explore.categories +package fr.free.nrw.commons.explore.categories.search import fr.free.nrw.commons.di.CommonsApplicationModule import fr.free.nrw.commons.explore.paging.BasePagingPresenter diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoryFragment.kt similarity index 79% rename from app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.kt rename to app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoryFragment.kt index 3393aace5..adff7d263 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoryFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/search/SearchCategoryFragment.kt @@ -1,9 +1,8 @@ -package fr.free.nrw.commons.explore.categories +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 javax.inject.Inject /** @@ -19,7 +18,9 @@ class SearchCategoryFragment : BasePagingFragment() { get() = presenter override val pagedListAdapter by lazy { - PagedSearchCategoriesAdapter { CategoryDetailsActivity.startYourself(context, it) } + 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/depictions/WikidataItemDetailsActivity.java b/app/src/main/java/fr/free/nrw/commons/explore/depictions/WikidataItemDetailsActivity.java index 176463706..688d5073c 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 @@ -143,7 +143,7 @@ public class WikidataItemDetailsActivity extends NavigationBaseActivity implemen */ @Override public Media getMediaAtPosition(int i) { - return depictionImagesListFragment.getImageAtPosition(i); + return depictionImagesListFragment.getMediaAtPosition(i); } /** @@ -168,7 +168,7 @@ public class WikidataItemDetailsActivity extends NavigationBaseActivity implemen */ @Override public int getTotalMediaCount() { - return depictionImagesListFragment.getTotalImagesCount(); + return depictionImagesListFragment.getTotalMediaCount(); } /** diff --git a/app/src/main/java/fr/free/nrw/commons/explore/media/MediaConverter.kt b/app/src/main/java/fr/free/nrw/commons/explore/media/MediaConverter.kt index db9096415..7e9e2159e 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/media/MediaConverter.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/media/MediaConverter.kt @@ -9,6 +9,7 @@ import fr.free.nrw.commons.wikidata.WikidataProperties import org.apache.commons.lang3.StringUtils import org.wikipedia.dataclient.mwapi.MwQueryPage import org.wikipedia.gallery.ExtMetadata +import org.wikipedia.gallery.ImageInfo import org.wikipedia.wikidata.DataValue import org.wikipedia.wikidata.Entities import java.text.ParseException @@ -16,9 +17,11 @@ import java.util.* import javax.inject.Inject class MediaConverter @Inject constructor() { - fun convert(page: MwQueryPage, entity: Entities.Entity): Media { - val imageInfo = page.imageInfo() - requireNotNull(imageInfo) { "No image info" } + fun convert( + page: MwQueryPage, + entity: Entities.Entity, + imageInfo: ImageInfo + ): Media { val metadata = imageInfo.metadata requireNotNull(metadata) { "No metadata" } return Media( 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 5b6df8780..9c960fb24 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 @@ -31,12 +31,12 @@ abstract class PageableMediaFragment : BasePagingFragment() { pagedListAdapter.unregisterAdapterDataObserver(simpleDataObserver) } - fun getImageAtPosition(position: Int): Media? = + fun getMediaAtPosition(position: Int): Media? = pagedListAdapter.currentList?.get(position)?.takeIf { it.filename != null } .also { pagedListAdapter.currentList?.loadAround(position) paginatedSearchResultsList.scrollToPosition(position) } - fun getTotalImagesCount(): Int = pagedListAdapter.itemCount + fun getTotalMediaCount(): Int = pagedListAdapter.itemCount } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentPresenterImpl.kt b/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentPresenterImpl.kt index c54e6aaab..ea2c3c4d0 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentPresenterImpl.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentPresenterImpl.kt @@ -2,8 +2,8 @@ package fr.free.nrw.commons.explore.media import fr.free.nrw.commons.Media import fr.free.nrw.commons.di.CommonsApplicationModule -import fr.free.nrw.commons.explore.paging.BasePagingPresenter import fr.free.nrw.commons.explore.paging.PagingContract +import fr.free.nrw.commons.explore.paging.BasePagingPresenter import io.reactivex.Scheduler import javax.inject.Inject import javax.inject.Named 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 70317402a..53f77752c 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 @@ -13,6 +13,7 @@ import javax.inject.Inject import javax.inject.Singleton const val PAGE_ID_PREFIX = "M" +const val CATEGORY_CONTINUATION_PREFIX = "category_" /** * Media Client to handle custom calls to Commons MediaWiki APIs @@ -61,14 +62,19 @@ class MediaClient @Inject constructor( * @return */ fun getMediaListFromCategory(category: String): Single> { - return responseToMediaList( - mediaInterface.getMediaListFromCategory( - category, - 10, - continuationStore["category_$category"] ?: emptyMap() - ), - "category_$category" - ) + val key = "$CATEGORY_CONTINUATION_PREFIX$category" + return if (hasMorePagesFor(key)) { + responseToMediaList( + mediaInterface.getMediaListFromCategory( + category, + 10, + continuationStore[key] ?: emptyMap() + ), + key + ) + } else { + Single.just(emptyList()) + } } /** @@ -144,7 +150,11 @@ class MediaClient @Inject constructor( getEntities(pages.map { "$PAGE_ID_PREFIX${it.pageId()}" }) .map { pages.zip(it.entities().values) - .map { (page, entity) -> mediaConverter.convert(page, entity) } + .mapNotNull { (page, entity) -> + page.imageInfo()?.let { + mediaConverter.convert(page, entity, it) + } + } } } @@ -189,12 +199,17 @@ class MediaClient @Inject constructor( * @return */ fun doesMediaListForUserHaveMorePages(userName: String): Boolean { - val key = "user_$userName" - return if (continuationExists.containsKey(key)) continuationExists[key]!! else true + 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") + } } diff --git a/app/src/main/res/layout/fragment_category_images.xml b/app/src/main/res/layout/fragment_category_images.xml deleted file mode 100644 index 8c3aa122a..000000000 --- a/app/src/main/res/layout/fragment_category_images.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/categories/media/PageableCategoriesMediaDataSourceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/categories/media/PageableCategoriesMediaDataSourceTest.kt new file mode 100644 index 000000000..e429b60f2 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/categories/media/PageableCategoriesMediaDataSourceTest.kt @@ -0,0 +1,49 @@ +package fr.free.nrw.commons.explore.categories.media + +import com.nhaarman.mockitokotlin2.never +import com.nhaarman.mockitokotlin2.verify +import com.nhaarman.mockitokotlin2.whenever +import fr.free.nrw.commons.explore.paging.LiveDataConverter +import fr.free.nrw.commons.media.MediaClient +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 PageableCategoriesMediaDataSourceTest { + @Mock + lateinit var mediaClient: MediaClient + + @Mock + lateinit var liveDataConverter: LiveDataConverter + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + } + + @Test + fun `loadFunction calls reset at position 0`() { + val dataSource = + PageableCategoriesMediaDataSource(liveDataConverter, mediaClient) + dataSource.onQueryUpdated("test") + whenever(mediaClient.getMediaListFromCategory("test")) + .thenReturn(Single.just(emptyList())) + assertThat(dataSource.loadFunction(-1, 0), `is`(emptyList())) + verify(mediaClient).resetCategoryContinuation("test") + } + + @Test + fun `loadFunction does not call reset at any other position`() { + val dataSource = + PageableCategoriesMediaDataSource(liveDataConverter, mediaClient) + dataSource.onQueryUpdated("test") + whenever(mediaClient.getMediaListFromCategory("test")) + .thenReturn(Single.just(emptyList())) + assertThat(dataSource.loadFunction(-1, 1), `is`(emptyList())) + verify(mediaClient, never()).resetCategoryContinuation("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/PageableCategoriesDataSourceTest.kt index 1561273c6..5a3cff5fe 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/PageableCategoriesDataSourceTest.kt @@ -3,7 +3,7 @@ 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.PageableCategoriesDataSource +import fr.free.nrw.commons.explore.categories.search.PageableCategoriesDataSource import io.reactivex.Observable import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/child/PageableChildDepictionsDataSourceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/child/PageableChildDepictionsDataSourceTest.kt index 08a623f96..9300bb9fa 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/child/PageableChildDepictionsDataSourceTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/depictions/child/PageableChildDepictionsDataSourceTest.kt @@ -1,5 +1,6 @@ package fr.free.nrw.commons.explore.depictions.child +import com.nhaarman.mockitokotlin2.verifyZeroInteractions import com.nhaarman.mockitokotlin2.whenever import depictedItem import fr.free.nrw.commons.explore.paging.LiveDataConverter diff --git a/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt index 15d6ab985..8c39e6e9d 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt @@ -164,7 +164,9 @@ class MediaClientTest { val entity: Entities.Entity = mock() whenever(entities.entities()).thenReturn(mapOf("id" to entity)) val media: Media = mock() - whenever(mediaConverter!!.convert(queryPage, entity)).thenReturn(media) + val imageInfo = mock() + whenever(queryPage.imageInfo()).thenReturn(imageInfo) + whenever(mediaConverter!!.convert(queryPage, entity, imageInfo)).thenReturn(media) return Pair(mockResponse, media) }