diff --git a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.kt b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.kt index d5adb84ed..5ff4e85a5 100644 --- a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.kt +++ b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.kt @@ -1,7 +1,7 @@ package fr.free.nrw.commons import androidx.core.text.HtmlCompat -import fr.free.nrw.commons.depictions.Media.DepictedImagesFragment.PAGE_ID_PREFIX +import fr.free.nrw.commons.media.PAGE_ID_PREFIX import fr.free.nrw.commons.media.IdAndCaptions import fr.free.nrw.commons.media.MediaClient import io.reactivex.Single diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/DepictionModule.java b/app/src/main/java/fr/free/nrw/commons/depictions/DepictionModule.java deleted file mode 100644 index a64d82967..000000000 --- a/app/src/main/java/fr/free/nrw/commons/depictions/DepictionModule.java +++ /dev/null @@ -1,27 +0,0 @@ -package fr.free.nrw.commons.depictions; - -import dagger.Binds; -import dagger.Module; -import fr.free.nrw.commons.depictions.Media.DepictedImagesContract; -import fr.free.nrw.commons.depictions.Media.DepictedImagesPresenter; -import fr.free.nrw.commons.depictions.subClass.SubDepictionListContract; -import fr.free.nrw.commons.depictions.subClass.SubDepictionListPresenter; - -/** - * The Dagger Module for explore:depictions related presenters and (some other objects maybe in future) - */ -@Module -public abstract class DepictionModule { - - @Binds - public abstract DepictedImagesContract.UserActionListener bindsDepictedImagesPresenter( - DepictedImagesPresenter - presenter - ); - - @Binds - public abstract SubDepictionListContract.UserActionListener bindsSubDepictionListPresenter( - SubDepictionListPresenter - presenter - ); -} diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/DepictionModule.kt b/app/src/main/java/fr/free/nrw/commons/depictions/DepictionModule.kt new file mode 100644 index 000000000..830c1b27d --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/depictions/DepictionModule.kt @@ -0,0 +1,23 @@ +package fr.free.nrw.commons.depictions + +import dagger.Binds +import dagger.Module +import fr.free.nrw.commons.depictions.Media.DepictedImagesContract +import fr.free.nrw.commons.depictions.Media.DepictedImagesPresenter +import fr.free.nrw.commons.depictions.subClass.SubDepictionListContract +import fr.free.nrw.commons.depictions.subClass.SubDepictionListPresenter + +/** + * The Dagger Module for explore:depictions related presenters and (some other objects maybe in future) + */ +@Module +abstract class DepictionModule { + @Binds + abstract fun SubDepictionListPresenter.bindsSubDepictionListPresenter() + : SubDepictionListContract.UserActionListener + + + @Binds + abstract fun DepictedImagesPresenter.bindsDepictedImagesContractPresenter() + : DepictedImagesContract.Presenter +} diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/GridViewAdapter.java b/app/src/main/java/fr/free/nrw/commons/depictions/GridViewAdapter.java deleted file mode 100644 index aeaa708cf..000000000 --- a/app/src/main/java/fr/free/nrw/commons/depictions/GridViewAdapter.java +++ /dev/null @@ -1,119 +0,0 @@ -package fr.free.nrw.commons.depictions; - -import android.content.Context; -import android.text.TextUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import androidx.annotation.Nullable; - -import com.facebook.drawee.view.SimpleDraweeView; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import fr.free.nrw.commons.Media; -import fr.free.nrw.commons.R; - -/** - * Adapter for Items in DepictionDetailsActivity - */ -public class GridViewAdapter extends ArrayAdapter { - - private List data; - - public GridViewAdapter(Context context, int layoutResourceId, List data) { - super(context, layoutResourceId, data); - this.data = data; - } - - /** - * Adds more item to the list - * Its triggered on scrolling down in the list - * @param images - */ - public void addItems(List images) { - if (data == null) { - data = new ArrayList<>(); - } - data.addAll(images); - notifyDataSetChanged(); - } - - /** - * Check the first item in the new list with old list and returns true if they are same - * Its triggered on successful response of the fetch images API. - * @param images - */ - public boolean containsAll(List images){ - if (images == null || images.isEmpty()) { - return false; - } - if (data == null) { - data = new ArrayList<>(); - return false; - } - if (data.size() == 0) { - return false; - } - String fileName = data.get(0).getFilename(); - String imageName = images.get(0).getFilename(); - return imageName.equals(fileName); - } - - @Override - public boolean isEmpty() { - return data == null || data.isEmpty(); - } - - /** - * Sets up the UI for the depicted image item - * @param position - * @param convertView - * @param parent - * @return - */ - @Override - public View getView(int position, View convertView, ViewGroup parent) { - - if (convertView == null) { - convertView = LayoutInflater.from(getContext()).inflate(R.layout.layout_depict_image, null); - } - - Media item = data.get(position); - SimpleDraweeView imageView = convertView.findViewById(R.id.depict_image_view); - TextView fileName = convertView.findViewById(R.id.depict_image_title); - TextView author = convertView.findViewById(R.id.depict_image_author); - fileName.setText(item.getDisplayTitle()); - setAuthorView(item, author); - imageView.setImageURI(item.getThumbUrl()); - return convertView; - } - - @Nullable - @Override - public Media getItem(int position) { - return data.get(position); - } - - /** - * Shows author information if its present - * @param item - * @param author - */ - private void setAuthorView(Media item, TextView author) { - if (!TextUtils.isEmpty(item.getCreator())) { - String uploadedByTemplate = getContext().getString(R.string.image_uploaded_by); - - String uploadedBy = String.format(Locale.getDefault(), uploadedByTemplate, item.getCreator()); - author.setText(uploadedBy); - } else { - author.setVisibility(View.GONE); - } - } - - } diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesContract.java b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesContract.java deleted file mode 100644 index e69d5cc3b..000000000 --- a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesContract.java +++ /dev/null @@ -1,98 +0,0 @@ -package fr.free.nrw.commons.depictions.Media; - -import android.widget.ListAdapter; - -import java.util.List; - -import fr.free.nrw.commons.BasePresenter; -import fr.free.nrw.commons.Media; - -/** - * Contract with which DepictedImagesFragment and its presenter will talk to each other - */ -public interface DepictedImagesContract { - - interface View { - - /** - * Handles the UI updates for no internet scenario - */ - void handleNoInternet(); - - /** - * Handles the UI updates for a error scenario - */ - void initErrorView(); - - /** - * Initializes the adapter with a list of Media objects - * - * @param mediaList List of new Media to be displayed - */ - void setAdapter(List mediaList); - - - /** - * Display snackbar - */ - void showSnackBar(); - - /** - * Inform the view that there are no more items to be loaded for this search query - * or reset the isLastPage for the current query - * @param isLastPage - */ - void setIsLastPage(boolean isLastPage); - - /** - * Set visibility of progressbar depending on the boolean value - */ - void progressBarVisible(Boolean value); - - /** - * It return an instance of gridView adapter which helps in extracting media details - * used by the gridView - * - * @return GridView Adapter - */ - ListAdapter getAdapter(); - - /** - * adds list to adapter - */ - void addItemsToAdapter(List media); - - /** - * Sets loading status depending on the boolean value - */ - void setLoadingStatus(Boolean value); - - /** - * 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 - */ - void handleSuccess(List collection); - - } - - interface UserActionListener extends BasePresenter { - - /** - * Checks for internet connection and then initializes the grid view with first 10 images of that depiction - */ - void initList(String entityId); - - /** - * Fetches more images for the item and adds it to the grid view adapter - * @param entityId - */ - void fetchMoreImages(String entityId); - - /** - * add items to query list - */ - void addItemsToQueryList(List collection); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesContract.kt b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesContract.kt new file mode 100644 index 000000000..c5d886d80 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesContract.kt @@ -0,0 +1,12 @@ +package fr.free.nrw.commons.depictions.Media + +import fr.free.nrw.commons.Media +import fr.free.nrw.commons.explore.PagingContract + +/** + * Contract with which DepictedImagesFragment and its presenter will talk to each other + */ +interface DepictedImagesContract { + interface View : PagingContract.View + interface Presenter : PagingContract.Presenter +} diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesFragment.java b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesFragment.java deleted file mode 100644 index 1efe63121..000000000 --- a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesFragment.java +++ /dev/null @@ -1,249 +0,0 @@ -package fr.free.nrw.commons.depictions.Media; - -import static android.view.View.GONE; -import static android.view.View.VISIBLE; - -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.NonNull; -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.depictions.GridViewAdapter; -import fr.free.nrw.commons.depictions.WikidataItemDetailsActivity; -import fr.free.nrw.commons.utils.NetworkUtils; -import fr.free.nrw.commons.utils.ViewUtil; -import java.util.List; -import javax.inject.Inject; -import timber.log.Timber; - -/** - * Fragment for showing image list after selected an item from SearchActivity In Explore - */ -public class DepictedImagesFragment extends DaggerFragment implements DepictedImagesContract.View { - - - public static final String PAGE_ID_PREFIX = "M"; - @BindView(R.id.statusMessage) - TextView statusTextView; - @BindView(R.id.loadingImagesProgressBar) - ProgressBar progressBar; - @BindView(R.id.depicts_image_list) - GridView gridView; - @BindView(R.id.parentLayout) - RelativeLayout parentLayout; - @Inject - DepictedImagesPresenter presenter; - private GridViewAdapter gridAdapter; - private String entityId = null; - private boolean isLastPage; - private boolean isLoading = true; - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_depict_image, container, false); - ButterKnife.bind(this, v); - presenter.onAttachView(this); - return v; - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - gridView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity()); - initViews(); - } - - /** - * Initializes the UI elements for the fragment - * Setup the grid view to and scroll listener for it - */ - private void initViews() { - String depictsName = getArguments().getString("wikidataItemName"); - entityId = getArguments().getString("entityId"); - if (getArguments() != null && depictsName != null) { - initList(); - setScrollListener(); - } - } - - private void initList() { - presenter.initList(entityId); - if (!NetworkUtils.isInternetConnectionEstablished(getContext())) { - handleNoInternet(); - } else { - presenter.initList(entityId); - } - } - - /** - * Handles the UI updates for no internet scenario - */ - @Override - public 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); - } - } - - /** - * Handles the UI updates for a error scenario - */ - @Override - public 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); - } - } - - /** - * Sets the scroll listener for the grid view so that more images are fetched when the user scrolls down - * Checks if the item 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 (!isLastPage && !isLoading && (firstVisibleItem + visibleItemCount >= totalItemCount)) { - isLoading = true; - if (!NetworkUtils.isInternetConnectionEstablished(getContext())) { - handleNoInternet(); - } else { - presenter.fetchMoreImages(entityId); - } - } - if (isLastPage) { - progressBar.setVisibility(GONE); - } - } - }); - } - - /** - * Display snackbar - */ - @Override - public void showSnackBar() { - ViewUtil.showShortSnackbar(parentLayout, R.string.error_loading_images); - } - - /** - * Set visibility of progressbar depending on the boolean value - */ - @Override - public void progressBarVisible(Boolean value) { - if (value) { - progressBar.setVisibility(VISIBLE); - } else { - progressBar.setVisibility(GONE); - } - } - - /** - * It return an instance of gridView adapter which helps in extracting media details - * used by the gridView - * - * @return GridView Adapter - */ - @Override - public ListAdapter getAdapter() { - return gridAdapter; - } - - /** - * Initializes the adapter with a list of Media objects - * - * @param mediaList List of new Media to be displayed - */ - @Override - public void setAdapter(List mediaList) { - gridAdapter = new fr.free.nrw.commons.depictions.GridViewAdapter(getContext(), R.layout.layout_depict_image, mediaList); - gridView.setAdapter(gridAdapter); - } - - /** - * adds list to adapter - */ - @Override - public void addItemsToAdapter(List media) { - gridAdapter.addAll(media); - gridAdapter.notifyDataSetChanged(); - } - - /** - * Sets loading status depending on the boolean value - */ - @Override - public void setLoadingStatus(Boolean value) { - if (!value) { - statusTextView.setVisibility(GONE); - } - isLoading = value; - } - - /** - * Inform the view that there are no more items to be loaded for this search query - * or reset the isLastPage for the current query - * @param isLastPage - */ - @Override - public void setIsLastPage(boolean isLastPage) { - this.isLastPage=isLastPage; - progressBar.setVisibility(GONE); - } - - - /** - * 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 - */ - @Override - public void handleSuccess(List collection) { - presenter.addItemsToQueryList(collection); - if (gridAdapter == null) { - setAdapter(collection); - } else { - if (gridAdapter.containsAll(collection)) { - return; - } - gridAdapter.addItems(collection); - - try { - ((WikidataItemDetailsActivity) getContext()).viewPagerNotifyDataSetChanged(); - } catch (RuntimeException e) { - Timber.e(e); - } - } - progressBar.setVisibility(GONE); - isLoading = false; - statusTextView.setVisibility(GONE); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesFragment.kt b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesFragment.kt new file mode 100644 index 000000000..e33a621ef --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesFragment.kt @@ -0,0 +1,28 @@ +package fr.free.nrw.commons.depictions.Media + +import android.os.Bundle +import android.view.View +import fr.free.nrw.commons.depictions.WikidataItemDetailsActivity +import fr.free.nrw.commons.explore.media.PageableMediaFragment +import javax.inject.Inject + +class DepictedImagesFragment : PageableMediaFragment(), DepictedImagesContract.View { + @Inject + lateinit var presenter: DepictedImagesContract.Presenter + + override val injectedPresenter + get() = presenter + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + onQueryUpdated(arguments!!.getString("entityId")!!) + } + + override fun onItemClicked(position: Int) { + (activity as WikidataItemDetailsActivity).onMediaClicked(position) + } + + override fun notifyViewPager() { + (activity as WikidataItemDetailsActivity).viewPagerNotifyDataSetChanged() + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesPresenter.java b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesPresenter.java deleted file mode 100644 index 77df508a2..000000000 --- a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesPresenter.java +++ /dev/null @@ -1,144 +0,0 @@ -package fr.free.nrw.commons.depictions.Media; - -import static fr.free.nrw.commons.di.CommonsApplicationModule.IO_THREAD; -import static fr.free.nrw.commons.di.CommonsApplicationModule.MAIN_THREAD; - -import android.annotation.SuppressLint; -import fr.free.nrw.commons.Media; -import fr.free.nrw.commons.kvstore.JsonKvStore; -import fr.free.nrw.commons.media.MediaClient; -import io.reactivex.Scheduler; -import io.reactivex.disposables.CompositeDisposable; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.List; -import javax.inject.Inject; -import javax.inject.Named; -import timber.log.Timber; - -/** - * Presenter for DepictedImagesFragment - */ -public class DepictedImagesPresenter implements DepictedImagesContract.UserActionListener { - - private static final DepictedImagesContract.View DUMMY = (DepictedImagesContract.View) Proxy - .newProxyInstance( - DepictedImagesContract.View.class.getClassLoader(), - new Class[]{DepictedImagesContract.View.class}, - (proxy, method, methodArgs) -> null); - MediaClient mediaClient; - @Named("default_preferences") - JsonKvStore depictionKvStore; - private final Scheduler ioScheduler; - private final Scheduler mainThreadScheduler; - private DepictedImagesContract.View view = DUMMY; - private CompositeDisposable compositeDisposable = new CompositeDisposable(); - /** - * Wikibase enitityId for the depicted Item - * Ex: Q9394 - */ - private List queryList = new ArrayList<>(); - - @Inject - public DepictedImagesPresenter(@Named("default_preferences") JsonKvStore depictionKvStore, - MediaClient mediaClient, - @Named(IO_THREAD) Scheduler ioScheduler, - @Named(MAIN_THREAD) Scheduler mainThreadScheduler) { - this.depictionKvStore = depictionKvStore; - this.ioScheduler = ioScheduler; - this.mainThreadScheduler = mainThreadScheduler; - this.mediaClient = mediaClient; - } - - @Override - public void onAttachView(DepictedImagesContract.View view) { - this.view = view; - } - - @Override - public void onDetachView() { - this.view = DUMMY; - } - - /** - * Checks for internet connection and then initializes the grid view with first 10 images of that depiction - */ - @SuppressLint("CheckResult") - @Override - public void initList(String entityId) { - view.setLoadingStatus(true); - view.progressBarVisible(true); - view.setIsLastPage(false); - compositeDisposable.add(mediaClient.fetchImagesForDepictedItem(entityId, 0) - .subscribeOn(ioScheduler) - .observeOn(mainThreadScheduler) - .subscribe(this::handleSuccess, this::handleError)); - } - - /** - * Fetches more images for the item and adds it to the grid view adapter - * @param entityId - */ - @SuppressLint("CheckResult") - @Override - public void fetchMoreImages(String entityId) { - view.progressBarVisible(true); - compositeDisposable.add(mediaClient.fetchImagesForDepictedItem(entityId, queryList.size()) - .subscribeOn(ioScheduler) - .observeOn(mainThreadScheduler) - .subscribe(this::handlePaginationSuccess, this::handleError)); - } - - /** - * Handles the success scenario - * it initializes the recycler view by adding items to the adapter - */ - private void handlePaginationSuccess(List media) { - queryList.addAll(media); - view.progressBarVisible(false); - view.addItemsToAdapter(media); - } - - /** - * Logs and handles API error scenario - * - * @param throwable - */ - public void handleError(Throwable throwable) { - Timber.e(throwable, "Error occurred while loading images inside items"); - try { - view.initErrorView(); - view.showSnackBar(); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - /** - * 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 - */ - public void handleSuccess(List collection) { - if (collection == null || collection.isEmpty()) { - if (queryList.isEmpty()) { - view.initErrorView(); - } else { - view.setIsLastPage(true); - } - } else { - this.queryList.addAll(collection); - view.handleSuccess(collection); - } - } - - - /** - * add items to query list - */ - @Override - public void addItemsToQueryList(List collection) { - queryList.addAll(collection); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesPresenter.kt b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesPresenter.kt new file mode 100644 index 000000000..28004c67e --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/depictions/Media/DepictedImagesPresenter.kt @@ -0,0 +1,17 @@ +package fr.free.nrw.commons.depictions.Media + +import fr.free.nrw.commons.Media +import fr.free.nrw.commons.di.CommonsApplicationModule +import fr.free.nrw.commons.explore.BasePagingPresenter +import io.reactivex.Scheduler +import javax.inject.Inject +import javax.inject.Named + +/** + * Presenter for DepictedImagesFragment + */ +class DepictedImagesPresenter @Inject constructor( + @Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler, + dataSourceFactory: PageableDepictedMediaDataSource +) : BasePagingPresenter(mainThreadScheduler, dataSourceFactory), + DepictedImagesContract.Presenter diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/Media/PageableDepictedMediaDataSource.kt b/app/src/main/java/fr/free/nrw/commons/depictions/Media/PageableDepictedMediaDataSource.kt new file mode 100644 index 000000000..708bc77b1 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/depictions/Media/PageableDepictedMediaDataSource.kt @@ -0,0 +1,17 @@ +package fr.free.nrw.commons.depictions.Media + +import fr.free.nrw.commons.Media +import fr.free.nrw.commons.explore.LiveDataConverter +import fr.free.nrw.commons.explore.PageableBaseDataSource +import fr.free.nrw.commons.explore.depictions.LoadFunction +import fr.free.nrw.commons.media.MediaClient +import javax.inject.Inject + +class PageableDepictedMediaDataSource @Inject constructor( + liveDataConverter: LiveDataConverter, + private val mediaClient: MediaClient +) : PageableBaseDataSource(liveDataConverter) { + override val loadFunction: LoadFunction = { loadSize: Int, startPosition: Int -> + mediaClient.fetchImagesForDepictedItem(query, loadSize, startPosition).blockingGet() + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/depictions/WikidataItemDetailsActivity.java b/app/src/main/java/fr/free/nrw/commons/depictions/WikidataItemDetailsActivity.java index 40ea07995..7aca8d272 100644 --- a/app/src/main/java/fr/free/nrw/commons/depictions/WikidataItemDetailsActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/depictions/WikidataItemDetailsActivity.java @@ -4,20 +4,13 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; 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.depictions.Media.DepictedImagesFragment; @@ -26,11 +19,13 @@ import fr.free.nrw.commons.explore.ViewPagerAdapter; import fr.free.nrw.commons.media.MediaDetailPagerFragment; import fr.free.nrw.commons.theme.NavigationBaseActivity; import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; +import java.util.ArrayList; +import java.util.List; /** * Activity to show depiction media, parent classes and child classes of depicted items in Explore */ -public class WikidataItemDetailsActivity extends NavigationBaseActivity implements MediaDetailPagerFragment.MediaDetailProvider, AdapterView.OnItemClickListener { +public class WikidataItemDetailsActivity extends NavigationBaseActivity implements MediaDetailPagerFragment.MediaDetailProvider { private FragmentManager supportFragmentManager; private DepictedImagesFragment depictionImagesListFragment; private MediaDetailPagerFragment mediaDetailPagerFragment; @@ -121,11 +116,11 @@ public class WikidataItemDetailsActivity extends NavigationBaseActivity implemen } + /** * Shows media detail fragment when user clicks on any image in the list */ - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { + public void onMediaClicked(int position) { tabLayout.setVisibility(View.GONE); viewPager.setVisibility(View.GONE); mediaContainer.setVisibility(View.VISIBLE); @@ -152,12 +147,7 @@ public class WikidataItemDetailsActivity extends NavigationBaseActivity implemen */ @Override public Media getMediaAtPosition(int i) { - if (depictionImagesListFragment.getAdapter() == null) { - // not yet ready to return data - return null; - } else { - return (Media) depictionImagesListFragment.getAdapter().getItem(i); - } + return depictionImagesListFragment.getImageAtPosition(i); } /** @@ -182,10 +172,7 @@ public class WikidataItemDetailsActivity extends NavigationBaseActivity implemen */ @Override public int getTotalMediaCount() { - if (depictionImagesListFragment.getAdapter() == null) { - return 0; - } - return depictionImagesListFragment.getAdapter().getCount(); + return depictionImagesListFragment.getTotalImagesCount(); } /** diff --git a/app/src/main/java/fr/free/nrw/commons/explore/BaseSearchFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/BasePagingFragment.kt similarity index 88% rename from app/src/main/java/fr/free/nrw/commons/explore/BaseSearchFragment.kt rename to app/src/main/java/fr/free/nrw/commons/explore/BasePagingFragment.kt index ae4c2cd9c..df85e1cc2 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/BaseSearchFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/BasePagingFragment.kt @@ -20,12 +20,11 @@ import fr.free.nrw.commons.utils.ViewUtil import kotlinx.android.synthetic.main.fragment_search_paginated.* -abstract class BaseSearchFragment : CommonsDaggerSupportFragment(), - SearchFragmentContract.View { +abstract class BasePagingFragment : CommonsDaggerSupportFragment(), + PagingContract.View { abstract val pagedListAdapter: PagedListAdapter - abstract val injectedPresenter: SearchFragmentContract.Presenter - abstract val emptyTemplateTextId: Int + abstract val injectedPresenter: PagingContract.Presenter abstract val errorTextId: Int private val loadingAdapter by lazy { FooterAdapter { injectedPresenter.retryFailedRequest() } } private val mergeAdapter by lazy { MergeAdapter(pagedListAdapter, loadingAdapter) } @@ -49,11 +48,12 @@ abstract class BaseSearchFragment : CommonsDaggerSupportFragment(), ) } - override fun observeSearchResults(searchResults: LiveData>) { + override fun observePagingResults(searchResults: LiveData>) { this.searchResults?.removeObservers(viewLifecycleOwner) this.searchResults = searchResults searchResults.observe(viewLifecycleOwner, Observer { - pagedListAdapter.submitList(it) }) + pagedListAdapter.submitList(it) + }) } override fun onAttach(context: Context) { @@ -61,7 +61,6 @@ abstract class BaseSearchFragment : CommonsDaggerSupportFragment(), injectedPresenter.onAttachView(this) } - override fun onDetach() { super.onDetach() injectedPresenter.onDetachView() @@ -84,10 +83,12 @@ abstract class BaseSearchFragment : CommonsDaggerSupportFragment(), } override fun showEmptyText(query: String) { - contentNotFound.text = getString(emptyTemplateTextId, query) + contentNotFound.text = getEmptyText(query) contentNotFound.visibility = VISIBLE } + abstract fun getEmptyText(query: String): String + override fun hideEmptyText() { contentNotFound.visibility = GONE } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/BaseSearchPresenter.kt b/app/src/main/java/fr/free/nrw/commons/explore/BasePagingPresenter.kt similarity index 70% rename from app/src/main/java/fr/free/nrw/commons/explore/BaseSearchPresenter.kt rename to app/src/main/java/fr/free/nrw/commons/explore/BasePagingPresenter.kt index f21f391c9..c26d13fba 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/BaseSearchPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/BasePagingPresenter.kt @@ -7,25 +7,25 @@ import io.reactivex.disposables.CompositeDisposable import timber.log.Timber -abstract class BaseSearchPresenter( +abstract class BasePagingPresenter( val mainThreadScheduler: Scheduler, - val pageableDataSource: PageableDataSource -) : SearchFragmentContract.Presenter { + val pageableBaseDataSource: PageableBaseDataSource +) : PagingContract.Presenter { - private val DUMMY: SearchFragmentContract.View = proxy() - private var view: SearchFragmentContract.View = DUMMY + private val DUMMY: PagingContract.View = proxy() + private var view: PagingContract.View = DUMMY private val compositeDisposable = CompositeDisposable() override val listFooterData = MutableLiveData>().apply { value = emptyList() } - override fun onAttachView(view: SearchFragmentContract.View) { + override fun onAttachView(view: PagingContract.View) { this.view = view compositeDisposable.addAll( - pageableDataSource.searchResults.subscribe(view::observeSearchResults), - pageableDataSource.loadingStates + pageableBaseDataSource.pagingResults.subscribe(view::observePagingResults), + pageableBaseDataSource.loadingStates .observeOn(mainThreadScheduler) .subscribe(::onLoadingState, Timber::e), - pageableDataSource.noItemsLoadedQueries.subscribe(view::showEmptyText) + pageableBaseDataSource.noItemsLoadedQueries.subscribe(view::showEmptyText) ) } @@ -50,7 +50,7 @@ abstract class BaseSearchPresenter( } override fun retryFailedRequest() { - pageableDataSource.retryFailedRequest() + pageableBaseDataSource.retryFailedRequest() } override fun onDetachView() { @@ -59,7 +59,7 @@ abstract class BaseSearchPresenter( } override fun onQueryUpdated(query: String) { - pageableDataSource.onQueryUpdated(query) + pageableBaseDataSource.onQueryUpdated(query) } } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/SearchFragmentContract.kt b/app/src/main/java/fr/free/nrw/commons/explore/PagingContract.kt similarity index 84% rename from app/src/main/java/fr/free/nrw/commons/explore/SearchFragmentContract.kt rename to app/src/main/java/fr/free/nrw/commons/explore/PagingContract.kt index b81608c27..6bbfa1491 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/SearchFragmentContract.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/PagingContract.kt @@ -4,10 +4,10 @@ import androidx.lifecycle.LiveData import androidx.paging.PagedList import fr.free.nrw.commons.BasePresenter -interface SearchFragmentContract { +interface PagingContract { interface View { fun showSnackbar() - fun observeSearchResults(searchResults: LiveData>) + fun observePagingResults(searchResults: LiveData>) fun showInitialLoadInProgress() fun hideInitialLoadProgress() fun showEmptyText(query: String) diff --git a/app/src/main/java/fr/free/nrw/commons/explore/SearchDataSource.kt b/app/src/main/java/fr/free/nrw/commons/explore/PagingDataSource.kt similarity index 100% rename from app/src/main/java/fr/free/nrw/commons/explore/SearchDataSource.kt rename to app/src/main/java/fr/free/nrw/commons/explore/PagingDataSource.kt diff --git a/app/src/main/java/fr/free/nrw/commons/explore/SearchDataSourceFactory.kt b/app/src/main/java/fr/free/nrw/commons/explore/PagingDataSourceFactory.kt similarity index 82% rename from app/src/main/java/fr/free/nrw/commons/explore/SearchDataSourceFactory.kt rename to app/src/main/java/fr/free/nrw/commons/explore/PagingDataSourceFactory.kt index c51d022c9..5629ab680 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/SearchDataSourceFactory.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/PagingDataSourceFactory.kt @@ -14,25 +14,25 @@ import javax.inject.Inject private const val PAGE_SIZE = 50 private const val INITIAL_LOAD_SIZE = 50 -abstract class PageableDataSource(private val liveDataConverter: LiveDataConverter) { +abstract class PageableBaseDataSource(private val liveDataConverter: LiveDataConverter) { lateinit var query: String - private val dataSourceFactoryFactory: () -> SearchDataSourceFactory = { + private val dataSourceFactoryFactory: () -> PagingDataSourceFactory = { dataSourceFactory(_loadingStates, loadFunction) } private val _loadingStates = PublishProcessor.create() val loadingStates: Flowable = _loadingStates - private val _searchResults = PublishProcessor.create>>() - val searchResults: Flowable>> = _searchResults + private val _pagingResults = PublishProcessor.create>>() + val pagingResults: Flowable>> = _pagingResults private val _noItemsLoadedEvent = PublishProcessor.create() val noItemsLoadedQueries: Flowable = _noItemsLoadedEvent - private var currentFactory: SearchDataSourceFactory? = null + private var currentFactory: PagingDataSourceFactory? = null abstract val loadFunction: LoadFunction fun onQueryUpdated(query: String) { this.query = query - _searchResults.offer( + _pagingResults.offer( liveDataConverter.convert(dataSourceFactoryFactory().also { currentFactory = it }) { _noItemsLoadedEvent.offer(query) } @@ -46,7 +46,7 @@ abstract class PageableDataSource(private val liveDataConverter: LiveDataConv class LiveDataConverter @Inject constructor() { fun convert( - dataSourceFactory: SearchDataSourceFactory, + dataSourceFactory: PagingDataSourceFactory, zeroItemsLoadedFunction: () -> Unit ): LiveData> { return dataSourceFactory.toLiveData( @@ -65,7 +65,7 @@ class LiveDataConverter @Inject constructor() { } -abstract class SearchDataSourceFactory(val loadingStates: LoadingStates) : +abstract class PagingDataSourceFactory(val loadingStates: LoadingStates) : DataSource.Factory() { private var currentDataSource: SearchDataSource? = null abstract val loadFunction: LoadFunction @@ -80,7 +80,7 @@ abstract class SearchDataSourceFactory(val loadingStates: LoadingStates) : } fun dataSourceFactory(loadingStates: LoadingStates, loadFunction: LoadFunction) = - object : SearchDataSourceFactory(loadingStates) { + object : PagingDataSourceFactory(loadingStates) { override val loadFunction: LoadFunction = loadFunction } 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 29d8cbe0c..ebb0b1ad7 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 @@ -269,9 +269,7 @@ public class SearchActivity extends NavigationBaseActivity */ @Override public void requestMoreImages() { - if (searchMediaFragment!=null){ - searchMediaFragment.requestMoreImages(); - } + //unneeded } @Override protected void onDestroy() { diff --git a/app/src/main/java/fr/free/nrw/commons/explore/SearchCategoriesFragmentPresenter.kt b/app/src/main/java/fr/free/nrw/commons/explore/SearchCategoriesFragmentPresenter.kt index 3de2c9778..18105baff 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/SearchCategoriesFragmentPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/SearchCategoriesFragmentPresenter.kt @@ -10,5 +10,5 @@ import javax.inject.Named class SearchCategoriesFragmentPresenter @Inject constructor( @Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler, dataSourceFactory: PageableCategoriesDataSource -) : BaseSearchPresenter(mainThreadScheduler, dataSourceFactory), +) : BasePagingPresenter(mainThreadScheduler, dataSourceFactory), SearchCategoriesFragmentContract.Presenter 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 cac220c18..628394438 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 @@ -14,18 +14,14 @@ import fr.free.nrw.commons.explore.media.SearchMediaFragmentPresenter @Module abstract class SearchModule { @Binds - abstract fun bindsSearchDepictionsFragmentPresenter( - presenter: SearchDepictionsFragmentPresenter - ): SearchDepictionsFragmentContract.Presenter + abstract fun SearchDepictionsFragmentPresenter.bindsSearchDepictionsFragmentPresenter() + : SearchDepictionsFragmentContract.Presenter @Binds - abstract fun bindsSearchCategoriesFragmentPresenter( - presenter: SearchCategoriesFragmentPresenter - ): SearchCategoriesFragmentContract.Presenter + abstract fun SearchCategoriesFragmentPresenter.bindsSearchCategoriesFragmentPresenter() + : SearchCategoriesFragmentContract.Presenter @Binds - abstract fun bindsSearchMediaFragmentPresenter( - presenter: SearchMediaFragmentPresenter - ): SearchMediaFragmentContract.Presenter - + abstract fun SearchMediaFragmentPresenter.bindsSearchMediaFragmentPresenter() + : SearchMediaFragmentContract.Presenter } 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/PageableCategoriesDataSource.kt index 67caaf1ab..4599b132a 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/PageableCategoriesDataSource.kt @@ -2,13 +2,13 @@ package fr.free.nrw.commons.explore.categories import fr.free.nrw.commons.category.CategoryClient import fr.free.nrw.commons.explore.LiveDataConverter -import fr.free.nrw.commons.explore.PageableDataSource +import fr.free.nrw.commons.explore.PageableBaseDataSource import javax.inject.Inject class PageableCategoriesDataSource @Inject constructor( liveDataConverter: LiveDataConverter, val categoryClient: CategoryClient -) : PageableDataSource(liveDataConverter) { +) : PageableBaseDataSource(liveDataConverter) { override val loadFunction = { loadSize: Int, startPosition: Int -> categoryClient.searchCategories(query, loadSize, startPosition).blockingFirst() diff --git a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesFragmentContract.kt b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesFragmentContract.kt index 97defd543..786556b0a 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesFragmentContract.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/categories/SearchCategoriesFragmentContract.kt @@ -1,8 +1,8 @@ package fr.free.nrw.commons.explore.categories -import fr.free.nrw.commons.explore.SearchFragmentContract +import fr.free.nrw.commons.explore.PagingContract interface SearchCategoriesFragmentContract { - interface View : SearchFragmentContract.View - interface Presenter : SearchFragmentContract.Presenter + interface View : PagingContract.View + interface Presenter : PagingContract.Presenter } 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/SearchCategoryFragment.kt index da5058fe0..0055d11dd 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/SearchCategoryFragment.kt @@ -2,25 +2,25 @@ package fr.free.nrw.commons.explore.categories import fr.free.nrw.commons.R import fr.free.nrw.commons.category.CategoryDetailsActivity -import fr.free.nrw.commons.explore.BaseSearchFragment -import fr.free.nrw.commons.explore.SearchFragmentContract +import fr.free.nrw.commons.explore.BasePagingFragment +import fr.free.nrw.commons.explore.PagingContract import javax.inject.Inject /** * Displays the category search screen. */ -class SearchCategoryFragment : BaseSearchFragment() { +class SearchCategoryFragment : BasePagingFragment() { @Inject lateinit var presenter: SearchCategoriesFragmentContract.Presenter - override val emptyTemplateTextId: Int = R.string.categories_not_found - override val errorTextId: Int = R.string.error_loading_categories - override val injectedPresenter: SearchFragmentContract.Presenter + override val injectedPresenter get() = presenter override val pagedListAdapter by lazy { PagedSearchCategoriesAdapter { CategoryDetailsActivity.startYourself(context, it) } } + + override fun getEmptyText(query: String) = getString(R.string.categories_not_found, query) } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/PageableDepictionsDataSource.kt b/app/src/main/java/fr/free/nrw/commons/explore/depictions/PageableDepictionsDataSource.kt index f6abeec60..aa60d9318 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/PageableDepictionsDataSource.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/PageableDepictionsDataSource.kt @@ -2,7 +2,7 @@ package fr.free.nrw.commons.explore.depictions import fr.free.nrw.commons.explore.LiveDataConverter import fr.free.nrw.commons.explore.LoadingState -import fr.free.nrw.commons.explore.PageableDataSource +import fr.free.nrw.commons.explore.PageableBaseDataSource import fr.free.nrw.commons.upload.structure.depictions.DepictedItem import io.reactivex.processors.PublishProcessor import javax.inject.Inject @@ -13,7 +13,7 @@ typealias LoadingStates = PublishProcessor class PageableDepictionsDataSource @Inject constructor( liveDataConverter: LiveDataConverter, val depictsClient: DepictsClient -) : PageableDataSource(liveDataConverter) { +) : PageableBaseDataSource(liveDataConverter) { override val loadFunction = { loadSize: Int, startPosition: Int -> depictsClient.searchForDepictions(query, loadSize, startPosition).blockingGet() diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragment.kt index 11932dfc3..51f7448da 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragment.kt @@ -2,26 +2,26 @@ package fr.free.nrw.commons.explore.depictions import fr.free.nrw.commons.R import fr.free.nrw.commons.depictions.WikidataItemDetailsActivity -import fr.free.nrw.commons.explore.BaseSearchFragment +import fr.free.nrw.commons.explore.BasePagingFragment import fr.free.nrw.commons.upload.structure.depictions.DepictedItem import javax.inject.Inject /** * Display depictions in search fragment */ -class SearchDepictionsFragment : BaseSearchFragment(), +class SearchDepictionsFragment : BasePagingFragment(), SearchDepictionsFragmentContract.View { @Inject lateinit var presenter: SearchDepictionsFragmentContract.Presenter - override val emptyTemplateTextId: Int = R.string.depictions_not_found - override val errorTextId: Int = R.string.error_loading_depictions - override val injectedPresenter: SearchDepictionsFragmentContract.Presenter + override val injectedPresenter get() = presenter override val pagedListAdapter by lazy { DepictionAdapter { WikidataItemDetailsActivity.startYourself(context, it) } } + + override fun getEmptyText(query: String) = getString(R.string.depictions_not_found, query) } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentContract.kt b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentContract.kt index 3f4da119e..54e0f9288 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentContract.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentContract.kt @@ -1,12 +1,12 @@ package fr.free.nrw.commons.explore.depictions -import fr.free.nrw.commons.explore.SearchFragmentContract +import fr.free.nrw.commons.explore.PagingContract import fr.free.nrw.commons.upload.structure.depictions.DepictedItem /** * The contract with with SearchDepictionsFragment and its presenter would talk to each other */ interface SearchDepictionsFragmentContract { - interface View : SearchFragmentContract.View - interface Presenter : SearchFragmentContract.Presenter + interface View : PagingContract.View + interface Presenter : PagingContract.Presenter } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentPresenter.kt b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentPresenter.kt index dbf0e6e63..ccc443918 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/SearchDepictionsFragmentPresenter.kt @@ -1,7 +1,7 @@ package fr.free.nrw.commons.explore.depictions import fr.free.nrw.commons.di.CommonsApplicationModule -import fr.free.nrw.commons.explore.BaseSearchPresenter +import fr.free.nrw.commons.explore.BasePagingPresenter import fr.free.nrw.commons.upload.structure.depictions.DepictedItem import io.reactivex.Scheduler import javax.inject.Inject @@ -13,5 +13,5 @@ import javax.inject.Named class SearchDepictionsFragmentPresenter @Inject constructor( @Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler, dataSourceFactory: PageableDepictionsDataSource -) : BaseSearchPresenter(mainThreadScheduler, dataSourceFactory), +) : BasePagingPresenter(mainThreadScheduler, dataSourceFactory), SearchDepictionsFragmentContract.Presenter diff --git a/app/src/main/java/fr/free/nrw/commons/explore/media/PageableMediaDataSource.kt b/app/src/main/java/fr/free/nrw/commons/explore/media/PageableMediaDataSource.kt index c39992c62..d5b4645e2 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/media/PageableMediaDataSource.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/media/PageableMediaDataSource.kt @@ -2,7 +2,7 @@ package fr.free.nrw.commons.explore.media import fr.free.nrw.commons.Media import fr.free.nrw.commons.explore.LiveDataConverter -import fr.free.nrw.commons.explore.PageableDataSource +import fr.free.nrw.commons.explore.PageableBaseDataSource import fr.free.nrw.commons.explore.depictions.LoadFunction import fr.free.nrw.commons.media.MediaClient import javax.inject.Inject @@ -10,7 +10,7 @@ import javax.inject.Inject class PageableMediaDataSource @Inject constructor( liveDataConverter: LiveDataConverter, private val mediaClient: MediaClient -) : PageableDataSource(liveDataConverter) { +) : PageableBaseDataSource(liveDataConverter) { override val loadFunction: LoadFunction = { loadSize: Int, startPosition: Int -> mediaClient.getMediaListFromSearch(query, loadSize, startPosition).blockingGet() } 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 new file mode 100644 index 000000000..1c911899d --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/explore/media/PageableMediaFragment.kt @@ -0,0 +1,42 @@ +package fr.free.nrw.commons.explore.media + +import android.os.Bundle +import android.view.View +import fr.free.nrw.commons.Media +import fr.free.nrw.commons.R +import fr.free.nrw.commons.explore.BasePagingFragment +import kotlinx.android.synthetic.main.fragment_search_paginated.* + + +abstract class PageableMediaFragment : BasePagingFragment() { + override val pagedListAdapter by lazy { PagedMediaAdapter(::onItemClicked) } + + override val errorTextId: Int = R.string.error_loading_images + + override fun getEmptyText(query: String) = getString(R.string.no_images_found) + + protected abstract fun onItemClicked(position: Int) + + protected abstract fun notifyViewPager() + + private val simpleDataObserver = SimpleDataObserver { notifyViewPager() } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + pagedListAdapter.registerAdapterDataObserver(simpleDataObserver) + } + + override fun onDestroyView() { + super.onDestroyView() + pagedListAdapter.unregisterAdapterDataObserver(simpleDataObserver) + } + + fun getImageAtPosition(position: Int): Media? = + pagedListAdapter.currentList?.get(position)?.takeIf { it.filename != null } + .also { + pagedListAdapter.currentList?.loadAround(position) + paginatedSearchResultsList.scrollToPosition(position) + } + + fun getTotalImagesCount(): Int = pagedListAdapter.itemCount +} diff --git a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaAdapter.kt b/app/src/main/java/fr/free/nrw/commons/explore/media/PagedMediaAdapter.kt similarity index 96% rename from app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaAdapter.kt rename to app/src/main/java/fr/free/nrw/commons/explore/media/PagedMediaAdapter.kt index 422e64438..3b8096553 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaAdapter.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/media/PagedMediaAdapter.kt @@ -10,7 +10,7 @@ import fr.free.nrw.commons.explore.BaseViewHolder import fr.free.nrw.commons.explore.inflate import kotlinx.android.synthetic.main.layout_category_images.* -class SearchImagesAdapter(private val onImageClicked: (Int) -> Unit) : +class PagedMediaAdapter(private val onImageClicked: (Int) -> Unit) : PagedListAdapter(object : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: Media, newItem: Media) = oldItem.pageId == newItem.pageId diff --git a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragment.kt index 677e306e1..feb7e3db2 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragment.kt @@ -1,57 +1,26 @@ package fr.free.nrw.commons.explore.media -import android.os.Bundle -import android.view.View -import fr.free.nrw.commons.Media -import fr.free.nrw.commons.R -import fr.free.nrw.commons.explore.BaseSearchFragment +import fr.free.nrw.commons.category.CategoryImagesCallback import fr.free.nrw.commons.explore.SearchActivity import javax.inject.Inject /** * Displays the image search screen. */ -class SearchMediaFragment : BaseSearchFragment(), SearchMediaFragmentContract.View { +class SearchMediaFragment : PageableMediaFragment(), SearchMediaFragmentContract.View { @Inject lateinit var presenter: SearchMediaFragmentContract.Presenter - override val emptyTemplateTextId: Int = R.string.depictions_not_found - - override val errorTextId: Int = R.string.error_loading_images - - override val injectedPresenter: SearchMediaFragmentContract.Presenter + override val injectedPresenter get() = presenter - override val pagedListAdapter by lazy { - SearchImagesAdapter { - (context as SearchActivity?)!!.onSearchImageClicked(it) - } + override fun onItemClicked(position: Int) { + (context as SearchActivity?)!!.onSearchImageClicked(position) } - private val simpleDataObserver = SimpleDataObserver { notifyViewPager() } - - fun requestMoreImages() { - // This functionality is replaced by a dataSetObserver and by using loadAround + override fun notifyViewPager() { + (activity as CategoryImagesCallback).viewPagerNotifyDataSetChanged() } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - pagedListAdapter.registerAdapterDataObserver(simpleDataObserver) - } - - override fun onDestroyView() { - super.onDestroyView() - pagedListAdapter.unregisterAdapterDataObserver(simpleDataObserver) - } - - private fun notifyViewPager() { - (activity as SearchActivity).viewPagerNotifyDataSetChanged() - } - - fun getImageAtPosition(position: Int): Media? = - pagedListAdapter.currentList?.get(position)?.takeIf { it.filename != null } - .also { pagedListAdapter.currentList?.loadAround(position) } - - fun getTotalImagesCount(): Int = pagedListAdapter.itemCount } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentContract.kt b/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentContract.kt index 0995c2e42..4a26b9d72 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentContract.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentContract.kt @@ -1,10 +1,10 @@ package fr.free.nrw.commons.explore.media import fr.free.nrw.commons.Media -import fr.free.nrw.commons.explore.SearchFragmentContract +import fr.free.nrw.commons.explore.PagingContract interface SearchMediaFragmentContract { - interface View : SearchFragmentContract.View - interface Presenter : SearchFragmentContract.Presenter + interface View : PagingContract.View + interface Presenter : PagingContract.Presenter } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentPresenter.kt b/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentPresenter.kt index dcad9ad8f..663624da5 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/media/SearchMediaFragmentPresenter.kt @@ -2,7 +2,7 @@ package fr.free.nrw.commons.explore.media import fr.free.nrw.commons.Media import fr.free.nrw.commons.di.CommonsApplicationModule -import fr.free.nrw.commons.explore.BaseSearchPresenter +import fr.free.nrw.commons.explore.BasePagingPresenter import io.reactivex.Scheduler import javax.inject.Inject import javax.inject.Named @@ -10,5 +10,5 @@ import javax.inject.Named class SearchMediaFragmentPresenter @Inject constructor( @Named(CommonsApplicationModule.MAIN_THREAD) mainThreadScheduler: Scheduler, dataSourceFactory: PageableMediaDataSource -) : BaseSearchPresenter(mainThreadScheduler, dataSourceFactory), +) : BasePagingPresenter(mainThreadScheduler, dataSourceFactory), SearchMediaFragmentContract.Presenter 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 f0fe5f3bd..70317402a 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt @@ -2,7 +2,6 @@ package fr.free.nrw.commons.media import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.Media -import fr.free.nrw.commons.depictions.Media.DepictedImagesFragment.PAGE_ID_PREFIX import fr.free.nrw.commons.explore.media.MediaConverter import fr.free.nrw.commons.utils.CommonsDateUtil import io.reactivex.Single @@ -13,6 +12,8 @@ import java.util.* import javax.inject.Inject import javax.inject.Singleton +const val PAGE_ID_PREFIX = "M" + /** * Media Client to handle custom calls to Commons MediaWiki APIs */ @@ -105,16 +106,20 @@ class MediaClient @Inject constructor( /** * @return list of images for a particular depict entity */ - fun fetchImagesForDepictedItem(query: String, sroffset: Int): Single> { + fun fetchImagesForDepictedItem( + query: String, + srlimit: Int, + sroffset: Int + ): Single> { return responseToMediaList( mediaInterface.fetchImagesForDepictedItem( "haswbstatement:" + BuildConfig.DEPICTS_PROPERTY + "=" + query, + srlimit.toString(), sroffset.toString() ) ) } - private fun responseToMediaList( response: Single, key: String? = null @@ -133,11 +138,14 @@ class MediaClient @Inject constructor( } private fun mediaFromPageAndEntity(pages: List): Single> { - return getEntities(pages.map { "$PAGE_ID_PREFIX${it.pageId()}" }) - .map { - pages.zip(it.entities().values) - .map { (page, entity) -> mediaConverter.convert(page, entity) } - } + return if (pages.isEmpty()) + Single.just(emptyList()) + else + getEntities(pages.map { "$PAGE_ID_PREFIX${it.pageId()}" }) + .map { + pages.zip(it.entities().values) + .map { (page, entity) -> mediaConverter.convert(page, entity) } + } } /** diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java b/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java index b9a17f132..c104235a9 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java @@ -117,14 +117,14 @@ public interface MediaInterface { /** * Fetches list of images from a depiction entity - * - * @param query depictionEntityId + * @param query depictionEntityId + * @param srlimit the number of items to fetch * @param sroffset number od depictions already fetched, this is useful in implementing pagination */ - @GET("w/api.php?action=query&format=json&formatversion=2" + //Basic parameters "&generator=search&gsrnamespace=6" + //Search parameters MEDIA_PARAMS) - Single fetchImagesForDepictedItem(@Query("gsrsearch") String query, @Query("gsroffset") String sroffset); + Single fetchImagesForDepictedItem(@Query("gsrsearch") String query, + @Query("gsrlimit")String srlimit, @Query("gsroffset") String sroffset); } diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikiBaseClient.java b/app/src/main/java/fr/free/nrw/commons/wikidata/WikiBaseClient.java index 739981c8a..0208c3d57 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikiBaseClient.java +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikiBaseClient.java @@ -1,6 +1,6 @@ package fr.free.nrw.commons.wikidata; -import static fr.free.nrw.commons.depictions.Media.DepictedImagesFragment.PAGE_ID_PREFIX; +import static fr.free.nrw.commons.media.MediaClientKt.PAGE_ID_PREFIX; import static fr.free.nrw.commons.di.NetworkingModule.NAMED_COMMONS_CSRF; import fr.free.nrw.commons.upload.UploadResult; diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java index 7fedfc49e..e761c68ed 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java @@ -1,6 +1,7 @@ package fr.free.nrw.commons.wikidata; -import static fr.free.nrw.commons.depictions.Media.DepictedImagesFragment.PAGE_ID_PREFIX; + +import static fr.free.nrw.commons.media.MediaClientKt.PAGE_ID_PREFIX; import android.annotation.SuppressLint; import android.content.Context; diff --git a/app/src/main/res/layout/fragment_depict_image.xml b/app/src/main/res/layout/fragment_depict_image.xml deleted file mode 100644 index 9ec5ca0ea..000000000 --- a/app/src/main/res/layout/fragment_depict_image.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - diff --git a/app/src/main/res/layout/layout_depict_image.xml b/app/src/main/res/layout/layout_depict_image.xml deleted file mode 100644 index 8f0ddd874..000000000 --- a/app/src/main/res/layout/layout_depict_image.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/depictions/DepictedImagesPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/depictions/DepictedImagesPresenterTest.kt deleted file mode 100644 index f10f814f3..000000000 --- a/app/src/test/kotlin/fr/free/nrw/commons/depictions/DepictedImagesPresenterTest.kt +++ /dev/null @@ -1,63 +0,0 @@ -package fr.free.nrw.commons.depictions - -import fr.free.nrw.commons.Media -import fr.free.nrw.commons.depictions.Media.DepictedImagesFragment -import fr.free.nrw.commons.depictions.Media.DepictedImagesPresenter -import fr.free.nrw.commons.kvstore.JsonKvStore -import fr.free.nrw.commons.media.MediaClient -import io.reactivex.Single -import io.reactivex.schedulers.TestScheduler -import org.junit.Before -import org.junit.Test -import org.mockito.ArgumentMatchers -import org.mockito.Mock -import org.mockito.Mockito -import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations - -class DepictedImagesPresenterTest { - - @Mock - internal lateinit var view: DepictedImagesFragment - - lateinit var depictedImagesPresenter: DepictedImagesPresenter - - @Mock - lateinit var jsonKvStore: JsonKvStore - - @Mock - lateinit var mediaClient: MediaClient - - lateinit var testScheduler: TestScheduler - - val mediaList: ArrayList = ArrayList() - - @Mock - lateinit var mediaItem: Media - - var testSingle: Single>? = null - - - @Before - @Throws(Exception::class) - fun setUp() { - MockitoAnnotations.initMocks(this) - testScheduler = TestScheduler() - mediaList.add(mediaItem) - testSingle = Single.just(mediaList) - depictedImagesPresenter = DepictedImagesPresenter(jsonKvStore, - mediaClient, testScheduler, testScheduler) - depictedImagesPresenter.onAttachView(view) - } - - @Test - fun initList() { - Mockito.`when`( - mediaClient.fetchImagesForDepictedItem(ArgumentMatchers.anyString(), - ArgumentMatchers.anyInt()) - ).thenReturn(testSingle) - depictedImagesPresenter.initList("rabbit") - depictedImagesPresenter.handleSuccess(mediaList) - verify(view)?.handleSuccess(mediaList) - } -} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/depictions/Media/PageableDepictedMediaDataSourceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/depictions/Media/PageableDepictedMediaDataSourceTest.kt new file mode 100644 index 000000000..6e8aa2396 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/depictions/Media/PageableDepictedMediaDataSourceTest.kt @@ -0,0 +1,21 @@ +package fr.free.nrw.commons.depictions.Media + +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.whenever +import fr.free.nrw.commons.media.MediaClient +import io.reactivex.Single +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.`is` +import org.junit.Test + +class PageableDepictedMediaDataSourceTest{ + @Test + fun `loadFunction loads Media`() { + val mediaClient = mock() + whenever(mediaClient.fetchImagesForDepictedItem("test",0,1)) + .thenReturn(Single.just(emptyList())) + val pageableDepictedMediaDataSource = PageableDepictedMediaDataSource(mock(), mediaClient) + pageableDepictedMediaDataSource.onQueryUpdated("test") + assertThat(pageableDepictedMediaDataSource.loadFunction(0,1), `is`(emptyList())) + } +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/BaseSearchPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/BasePagingPresenterTest.kt similarity index 69% rename from app/src/test/kotlin/fr/free/nrw/commons/explore/BaseSearchPresenterTest.kt rename to app/src/test/kotlin/fr/free/nrw/commons/explore/BasePagingPresenterTest.kt index aa9996493..c78e343fb 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/explore/BaseSearchPresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/BasePagingPresenterTest.kt @@ -15,21 +15,21 @@ import org.junit.Test import org.mockito.Mock import org.mockito.MockitoAnnotations -class BaseSearchPresenterTest { +class BasePagingPresenterTest { @Rule @JvmField var instantTaskExecutorRule = InstantTaskExecutorRule() @Mock - internal lateinit var view: SearchFragmentContract.View + internal lateinit var view: PagingContract.View - private lateinit var baseSearchPresenter: BaseSearchPresenter + private lateinit var basePagingPresenter: BasePagingPresenter private lateinit var testScheduler: TestScheduler @Mock - private lateinit var pageableDataSource: PageableDataSource + private lateinit var pageableBaseDataSource: PageableBaseDataSource private var loadingStates: PublishProcessor = PublishProcessor.create() @@ -42,34 +42,34 @@ class BaseSearchPresenterTest { @Throws(Exception::class) fun setUp() { MockitoAnnotations.initMocks(this) - whenever(pageableDataSource.searchResults).thenReturn(searchResults) - whenever(pageableDataSource.loadingStates).thenReturn(loadingStates) - whenever(pageableDataSource.noItemsLoadedQueries) + whenever(pageableBaseDataSource.pagingResults).thenReturn(searchResults) + whenever(pageableBaseDataSource.loadingStates).thenReturn(loadingStates) + whenever(pageableBaseDataSource.noItemsLoadedQueries) .thenReturn(noItemLoadedQueries) testScheduler = TestScheduler() - baseSearchPresenter = - object : BaseSearchPresenter(testScheduler, pageableDataSource) {} - baseSearchPresenter.onAttachView(view) + basePagingPresenter = + object : BasePagingPresenter(testScheduler, pageableBaseDataSource) {} + basePagingPresenter.onAttachView(view) } @Test fun `searchResults emission updates the view`() { val pagedListLiveData = mock>>() searchResults.offer(pagedListLiveData) - verify(view).observeSearchResults(pagedListLiveData) + verify(view).observePagingResults(pagedListLiveData) } @Test fun `Loading offers a loading list item`() { onLoadingState(LoadingState.Loading) verify(view).hideEmptyText() - baseSearchPresenter.listFooterData.test().assertValue(listOf(FooterItem.LoadingItem)) + basePagingPresenter.listFooterData.test().assertValue(listOf(FooterItem.LoadingItem)) } @Test fun `Complete offers an empty list item and hides initial loader`() { onLoadingState(LoadingState.Complete) - baseSearchPresenter.listFooterData.test() + basePagingPresenter.listFooterData.test() .assertValue(emptyList()) verify(view).hideInitialLoadProgress() } @@ -83,11 +83,11 @@ class BaseSearchPresenterTest { @Test fun `Error offers a refresh list item, hides initial loader and shows error with a set text`() { - baseSearchPresenter.onQueryUpdated("test") + basePagingPresenter.onQueryUpdated("test") onLoadingState(LoadingState.Error) verify(view).showSnackbar() verify(view).hideInitialLoadProgress() - baseSearchPresenter.listFooterData.test().assertValue(listOf(FooterItem.RefreshItem)) + basePagingPresenter.listFooterData.test().assertValue(listOf(FooterItem.RefreshItem)) } @Test @@ -98,21 +98,21 @@ class BaseSearchPresenterTest { @Test fun `retryFailedRequest calls retry`() { - baseSearchPresenter.retryFailedRequest() - verify(pageableDataSource).retryFailedRequest() + basePagingPresenter.retryFailedRequest() + verify(pageableBaseDataSource).retryFailedRequest() } @Test fun `onDetachView stops subscriptions`() { - baseSearchPresenter.onDetachView() + basePagingPresenter.onDetachView() onLoadingState(LoadingState.Loading) - baseSearchPresenter.listFooterData.test().assertValue(emptyList()) + basePagingPresenter.listFooterData.test().assertValue(emptyList()) } @Test fun `onQueryUpdated updates dataSourceFactory`() { - baseSearchPresenter.onQueryUpdated("test") - verify(pageableDataSource).onQueryUpdated("test") + basePagingPresenter.onQueryUpdated("test") + verify(pageableBaseDataSource).onQueryUpdated("test") } private fun onLoadingState(loadingState: LoadingState) { diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/PageableDataSourceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/PageableBaseDataSourceTest.kt similarity index 72% rename from app/src/test/kotlin/fr/free/nrw/commons/explore/PageableDataSourceTest.kt rename to app/src/test/kotlin/fr/free/nrw/commons/explore/PageableBaseDataSourceTest.kt index 49222f2c3..5e8009ca3 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/explore/PageableDataSourceTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/PageableBaseDataSourceTest.kt @@ -10,17 +10,17 @@ import org.junit.Test import org.mockito.Mock import org.mockito.MockitoAnnotations -class PageableDataSourceTest { +class PageableBaseDataSourceTest { @Mock private lateinit var liveDataConverter: LiveDataConverter - private lateinit var pageableDataSource: PageableDataSource + private lateinit var pageableBaseDataSource: PageableBaseDataSource @Before fun setUp() { MockitoAnnotations.initMocks(this) - pageableDataSource = object: PageableDataSource(liveDataConverter){ + pageableBaseDataSource = object: PageableBaseDataSource(liveDataConverter){ override val loadFunction: LoadFunction get() = mock() @@ -30,16 +30,16 @@ class PageableDataSourceTest { @Test fun `onQueryUpdated emits new liveData`() { val (_, liveData) = expectNewLiveData() - pageableDataSource.searchResults.test() - .also { pageableDataSource.onQueryUpdated("test") } + pageableBaseDataSource.pagingResults.test() + .also { pageableBaseDataSource.onQueryUpdated("test") } .assertValue(liveData) } @Test fun `onQueryUpdated invokes livedatconverter with no items emitter`() { val (zeroItemsFuncCaptor, _) = expectNewLiveData() - pageableDataSource.onQueryUpdated("test") - pageableDataSource.noItemsLoadedQueries.test() + pageableBaseDataSource.onQueryUpdated("test") + pageableBaseDataSource.noItemsLoadedQueries.test() .also { zeroItemsFuncCaptor.firstValue.invoke() } .assertValue("test") } @@ -49,22 +49,22 @@ class PageableDataSourceTest { * */ @Test fun `retryFailedRequest does nothing without a factory`() { - pageableDataSource.retryFailedRequest() + pageableBaseDataSource.retryFailedRequest() } @Test @Ignore("Rewrite with Mockk constructor mocks") fun `retryFailedRequest retries with a factory`() { val (_, _, dataSourceFactoryCaptor) = expectNewLiveData() - pageableDataSource.onQueryUpdated("test") + pageableBaseDataSource.onQueryUpdated("test") val dataSourceFactory = spy(dataSourceFactoryCaptor.firstValue) - pageableDataSource.retryFailedRequest() + pageableBaseDataSource.retryFailedRequest() verify(dataSourceFactory).retryFailedRequest() } - private fun expectNewLiveData(): Triple Unit>, LiveData>, KArgumentCaptor>> { + private fun expectNewLiveData(): Triple Unit>, LiveData>, KArgumentCaptor>> { val captor = argumentCaptor<() -> Unit>() - val dataSourceFactoryCaptor = argumentCaptor>() + val dataSourceFactoryCaptor = argumentCaptor>() val liveData: LiveData> = mock() whenever(liveDataConverter.convert(dataSourceFactoryCaptor.capture(), captor.capture())) .thenReturn(liveData) diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/SearchDataSourceFactoryTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/PagingDataSourceFactoryTest.kt similarity index 90% rename from app/src/test/kotlin/fr/free/nrw/commons/explore/SearchDataSourceFactoryTest.kt rename to app/src/test/kotlin/fr/free/nrw/commons/explore/PagingDataSourceFactoryTest.kt index bbe6e9991..acb38de0d 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/explore/SearchDataSourceFactoryTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/PagingDataSourceFactoryTest.kt @@ -14,21 +14,21 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.MockitoAnnotations -class SearchDataSourceFactoryTest { +class PagingDataSourceFactoryTest { @Mock private lateinit var depictsClient: DepictsClient @Mock private lateinit var loadingStates: PublishProcessor - private lateinit var factory: SearchDataSourceFactory + private lateinit var factory: PagingDataSourceFactory private var function: (Int, Int) -> List = mock() @Before fun setUp() { MockitoAnnotations.initMocks(this) - factory = object : SearchDataSourceFactory(loadingStates) { + factory = object : PagingDataSourceFactory(loadingStates) { override val loadFunction get() = function } } 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 4dfe7c433..15d6ab985 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 @@ -139,7 +139,7 @@ class MediaClientTest { `when`(mediaInterface!!.getMedia(ArgumentMatchers.anyString())) .thenReturn(Single.just(mockResponse)) - mediaClient!!.getMedia("abcde").test().assertErrorMessage("empty list passed for ids") + mediaClient!!.getMedia("abcde").test().assertErrorMessage("List is empty.") } @Test