From bf50e749ece7ceba65be26d4fa5f8eec783dd9f2 Mon Sep 17 00:00:00 2001 From: Ujjwal Agrawal Date: Wed, 8 Aug 2018 12:45:06 +0530 Subject: [PATCH] Fixes #1801 (Media details view for Browse is lacking author field) in 2.8-release branch (#1810) * In media search results, rotating screen triggers crash fixed #1753 * Updated API to get Author name too * Crash fixed due to notifyDataSetChange * search API duplicate images fixed --- app/src/main/AndroidManifest.xml | 1 + .../category/CategoryDetailsActivity.java | 20 ++++++++++++ .../category/CategoryImagesActivity.java | 20 ++++++++++++ .../category/CategoryImagesListFragment.java | 25 ++++++++++++++- .../nrw/commons/explore/SearchActivity.java | 26 +++++++++++++++ .../explore/images/SearchImageFragment.java | 17 +++++++--- .../explore/images/SearchImagesRenderer.java | 4 +-- .../media/MediaDetailPagerFragment.java | 32 +++++++++++++++++-- .../mwapi/ApacheHttpClientMediaWikiApi.java | 32 +++++++++++-------- 9 files changed, 154 insertions(+), 23 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5a9643258..e80e2a84f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -114,6 +114,7 @@ diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.java index 3ab3c2c07..fce2fac5e 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.java @@ -250,4 +250,24 @@ public class CategoryDetailsActivity extends NavigationBaseActivity } super.onBackPressed(); } + + /** + * This method is called on success of API call for Images inside a category. + * The viewpager will notified that number of items have changed. + */ + public void viewPagerNotifyDataSetChanged() { + if (mediaDetails!=null){ + mediaDetails.notifyDataSetChanged(); + } + } + + /** + * This method is called when viewPager has reached its end. + * Fetches more images using search query and adds it to the grid view and viewpager adapter + */ + public void requestMoreImages() { + if (categoryImagesListFragment!=null){ + categoryImagesListFragment.fetchMoreImagesViewPager(); + } + } } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesActivity.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesActivity.java index 382134472..eafc46e68 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesActivity.java @@ -170,6 +170,16 @@ public class CategoryImagesActivity } } + /** + * This method is called on success of API call for featured Images. + * The viewpager will notified that number of items have changed. + */ + public void viewPagerNotifyDataSetChanged() { + if (mediaDetails!=null){ + mediaDetails.notifyDataSetChanged(); + } + } + /** * This method is called on from getCount of MediaDetailPagerFragment * The viewpager will contain same number of media items as that of media elements in adapter. @@ -236,4 +246,14 @@ public class CategoryImagesActivity return super.onOptionsItemSelected(item); } } + + /** + * This method is called when viewPager has reached its end. + * Fetches more images using search query and adds it to the gridView and viewpager adapter + */ + public void requestMoreImages() { + if (categoryImagesListFragment!=null){ + categoryImagesListFragment.fetchMoreImagesViewPager(); + } + } } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java index 385662a05..a78157ee2 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java @@ -190,6 +190,20 @@ public class CategoryImagesListFragment extends DaggerFragment { }); } + /** + * 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 */ @@ -228,8 +242,17 @@ public class CategoryImagesListFragment extends DaggerFragment { return; } gridAdapter.addItems(collection); + try { + ((CategoryImagesActivity) getContext()).viewPagerNotifyDataSetChanged(); + }catch (Exception e){ + e.printStackTrace(); + } + try { + ((CategoryDetailsActivity) getContext()).viewPagerNotifyDataSetChanged(); + }catch (Exception e){ + e.printStackTrace(); + } } - progressBar.setVisibility(GONE); isLoading = false; statusTextView.setVisibility(GONE); 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 f28065eb5..38d78fb34 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 @@ -1,5 +1,6 @@ package fr.free.nrw.commons.explore; +import android.content.res.Configuration; import android.database.DataSetObserver; import android.os.Bundle; import android.support.design.widget.TabLayout; @@ -52,6 +53,7 @@ public class SearchActivity extends NavigationBaseActivity implements MediaDetai private FragmentManager supportFragmentManager; private MediaDetailPagerFragment mediaDetails; ViewPagerAdapter viewPagerAdapter; + private String query; @Override protected void onCreate(Bundle savedInstanceState) { @@ -103,6 +105,7 @@ public class SearchActivity extends NavigationBaseActivity implements MediaDetai .debounce(500, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe( query -> { + this.query = query.toString(); //update image list if (!TextUtils.isEmpty(query)) { viewPager.setVisibility(View.VISIBLE); @@ -144,7 +147,16 @@ public class SearchActivity extends NavigationBaseActivity implements MediaDetai */ @Override public void notifyDatasetChanged() { + } + /** + * This method is called on success of API call for image Search. + * The viewpager will notified that number of items have changed. + */ + public void viewPagerNotifyDataSetChanged() { + if (mediaDetails!=null){ + mediaDetails.notifyDataSetChanged(); + } } /** @@ -194,6 +206,10 @@ public class SearchActivity extends NavigationBaseActivity implements MediaDetai mediaDetails.showImage(index); forceInitBackButton(); } + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + } /** * This method is called on Screen Rotation @@ -240,4 +256,14 @@ public class SearchActivity extends NavigationBaseActivity implements MediaDetai // https://stackoverflow.com/questions/6117967/how-to-remove-focus-without-setting-focus-to-another-control/15481511 viewPager.requestFocus(); } + + /** + * This method is called when viewPager has reached its end. + * Fetches more images using search query and adds it to the recycler view and viewpager adapter + */ + public void requestMoreImages() { + if (searchImageFragment!=null){ + searchImageFragment.addImagesToList(query); + } + } } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java index a503207e4..2c37f04ea 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImageFragment.java @@ -13,6 +13,8 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ProgressBar; import android.widget.TextView; +import android.widget.Toast; + import com.pedrogomez.renderers.RVRendererAdapter; import java.util.ArrayList; import java.util.Date; @@ -156,10 +158,15 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { * @param mediaList List of media to be added */ private void handlePaginationSuccess(List mediaList) { - queryList.addAll(mediaList); progressBar.setVisibility(View.GONE); - imagesAdapter.addAll(mediaList); - imagesAdapter.notifyDataSetChanged(); + if (mediaList.size()!=0){ + if (!queryList.get(queryList.size()-1).getFilename().equals(mediaList.get(mediaList.size()-1).getFilename())) { + queryList.addAll(mediaList); + imagesAdapter.addAll(mediaList); + imagesAdapter.notifyDataSetChanged(); + ((SearchActivity)getContext()).viewPagerNotifyDataSetChanged(); + } + } } @@ -179,6 +186,7 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { progressBar.setVisibility(View.GONE); imagesAdapter.addAll(mediaList); imagesAdapter.notifyDataSetChanged(); + ((SearchActivity)getContext()).viewPagerNotifyDataSetChanged(); // check if user is waiting for 5 seconds if yes then save search query to history. Handler handler = new Handler(); @@ -193,7 +201,6 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { private void handleError(Throwable throwable) { Timber.e(throwable, "Error occurred while loading queried images"); try { - initErrorView(); ViewUtil.showSnackbar(imagesRecyclerView, R.string.error_loading_images); }catch (Exception e){ e.printStackTrace(); @@ -239,7 +246,7 @@ public class SearchImageFragment extends CommonsDaggerSupportFragment { return null; } else { - return new Media(imagesAdapter.getItem(i).getFilename()); + return imagesAdapter.getItem(i); } } } diff --git a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesRenderer.java b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesRenderer.java index 42c044d70..022e8307e 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesRenderer.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/images/SearchImagesRenderer.java @@ -65,11 +65,11 @@ class SearchImagesRenderer extends Renderer { */ private void setAuthorView(Media item, TextView author) { if (item.getCreator() != null && !item.getCreator().equals("")) { - author.setVisibility(View.GONE); + author.setVisibility(View.VISIBLE); String uploadedByTemplate = getContext().getString(R.string.image_uploaded_by); author.setText(String.format(uploadedByTemplate, item.getCreator())); } else { - author.setVisibility(View.VISIBLE); + author.setVisibility(View.GONE); } } } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java index fc58ae990..d5e4fac2f 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java @@ -35,9 +35,12 @@ import javax.inject.Named; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; import fr.free.nrw.commons.auth.SessionManager; +import fr.free.nrw.commons.category.CategoryDetailsActivity; +import fr.free.nrw.commons.category.CategoryImagesActivity; import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.ContributionsActivity; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; +import fr.free.nrw.commons.explore.SearchActivity; import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.utils.ImageUtils; import timber.log.Timber; @@ -62,6 +65,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple ViewPager pager; private Boolean editable; private boolean isFeaturedImage; + MediaDetailAdapter adapter; public MediaDetailPagerFragment() { this(false, false); @@ -81,7 +85,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple ButterKnife.bind(this,view); pager.addOnPageChangeListener(this); - final MediaDetailAdapter adapter = new MediaDetailAdapter(getChildFragmentManager()); + adapter = new MediaDetailAdapter(getChildFragmentManager()); if (savedInstanceState != null) { final int pageNumber = savedInstanceState.getInt("current-page"); @@ -269,11 +273,35 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple public void showImage(int i) { Handler handler = new Handler(); - handler.postDelayed(() -> pager.setCurrentItem(i), 10); + handler.postDelayed(() -> pager.setCurrentItem(i), 5); + } + + /** + * The method notify the viewpager that number of items have changed. + */ + public void notifyDataSetChanged(){ + adapter.notifyDataSetChanged(); } @Override public void onPageScrolled(int i, float v, int i2) { + if (i+1 >= adapter.getCount()){ + try{ + ((CategoryImagesActivity) getContext()).requestMoreImages(); + }catch (Exception e){ + e.printStackTrace(); + } + try{ + ((CategoryDetailsActivity) getContext()).requestMoreImages(); + }catch (Exception e){ + e.printStackTrace(); + } + try{ + ((SearchActivity) getContext()).requestMoreImages(); + }catch (Exception e){ + e.printStackTrace(); + } + } getActivity().supportInvalidateOptionsMenu(); } diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index 2eb3f9b71..4cf0d8253 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -736,17 +736,21 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { @NonNull public List searchImages(String query, int offset) { List imageNodes = null; + List authorNodes = null; + CustomApiResult customApiResult; try { - imageNodes = api.action("query") + customApiResult= api.action("query") .param("format", "xml") - .param("list", "search") - .param("srwhat", "text") - .param("srnamespace", "6") - .param("srlimit", "25") - .param("sroffset",offset) - .param("srsearch", query) - .get() - .getNodes("/api/query/search/p/@title"); + .param("generator", "search") + .param("gsrwhat", "text") + .param("gsrnamespace", "6") + .param("gsrlimit", "25") + .param("gsroffset",offset) + .param("gsrsearch", query) + .param("prop", "imageinfo") + .get(); + imageNodes= customApiResult.getNodes("/api/query/pages/page/@title"); + authorNodes= customApiResult.getNodes("/api/query/pages/page/imageinfo/ii/@user"); } catch (IOException e) { Timber.e("Failed to obtain searchImages", e); } @@ -756,11 +760,13 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { } List images = new ArrayList<>(); - for (CustomApiResult imageNode : imageNodes) { - String imgName = imageNode.getDocument().getTextContent(); - images.add(new Media(imgName)); - } + for (int i=0; i< imageNodes.size();i++){ + String imgName = imageNodes.get(i).getDocument().getTextContent(); + Media media = new Media(imgName); + media.setCreator(authorNodes.get(i).getDocument().getTextContent()); + images.add(media); + } return images; }