mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-31 14:53:59 +01:00 
			
		
		
		
	
							parent
							
								
									0e5ba98c2e
								
							
						
					
					
						commit
						7817518462
					
				
					 29 changed files with 245 additions and 418 deletions
				
			
		|  | @ -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<Fragment> fragmentList = new ArrayList<>(); | ||||
|         List<String> 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 | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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<Media> 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<Media> 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; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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<ApplicationlessInjection> { | ||||
|     void inject(CommonsApplication application); | ||||
|  |  | |||
|  | @ -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(); | ||||
| } | ||||
|  |  | |||
|  | @ -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<Fragment> fragmentList = new ArrayList<>(); | ||||
|         List<String> 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 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  |  | |||
|  | @ -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(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  | @ -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() | ||||
|     } | ||||
| } | ||||
|  | @ -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<Media> | ||||
| 
 | ||||
| /** | ||||
|  * Presenter for DepictedImagesFragment | ||||
|  */ | ||||
| class CategoryMediaPresenterImpl @Inject constructor( | ||||
|     @Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler, | ||||
|     dataSourceFactory: PageableCategoriesMediaDataSource | ||||
| ) : BasePagingPresenter<Media>(mainThreadScheduler, dataSourceFactory), | ||||
|     CategoryMediaPresenter | ||||
|  | @ -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<Media>(liveDataConverter) { | ||||
|     override val loadFunction: LoadFunction<Media> = { loadSize: Int, startPosition: Int -> | ||||
|         if(startPosition == 0){ | ||||
|             mediaClient.resetCategoryContinuation(query) | ||||
|         } | ||||
|         mediaClient.getMediaListFromCategory(query).blockingGet() | ||||
|     } | ||||
| } | ||||
|  | @ -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 | ||||
|  | @ -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 | ||||
|  | @ -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<String>( | ||||
|     searchCategoryDelegate(onCateoryClicked), | ||||
|     searchCategoryDelegate( | ||||
|         onCateoryClicked | ||||
|     ), | ||||
|     areItemsTheSame = { oldItem, newItem -> oldItem == newItem } | ||||
| ) | ||||
|  | @ -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 | ||||
|  | @ -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 | ||||
|  | @ -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<String>() { | |||
|         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) | ||||
|  | @ -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(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  |  | |||
|  | @ -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( | ||||
|  |  | |||
|  | @ -31,12 +31,12 @@ abstract class PageableMediaFragment : BasePagingFragment<Media>() { | |||
|         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 | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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<List<Media>> { | ||||
|         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<Boolean> { | ||||
|         return pageMediaInterface.getMediaList(title) | ||||
|             .map { it.items.isNotEmpty() } | ||||
|     } | ||||
| 
 | ||||
|     fun resetCategoryContinuation(category: String) { | ||||
|         continuationExists.remove("$CATEGORY_CONTINUATION_PREFIX$category") | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Seán Mac Gillicuddy
						Seán Mac Gillicuddy