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
This commit is contained in:
Ujjwal Agrawal 2018-08-08 12:45:06 +05:30 committed by Josephine Lim
parent a5d4e8f739
commit bf50e749ec
9 changed files with 154 additions and 23 deletions

View file

@ -114,6 +114,7 @@
<activity
android:name=".explore.SearchActivity"
android:label="@string/title_activity_search"
android:configChanges="orientation|keyboardHidden"
android:parentActivityName=".contributions.ContributionsActivity"
/>

View file

@ -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();
}
}
}

View file

@ -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();
}
}
}

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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<Media> mediaList) {
queryList.addAll(mediaList);
progressBar.setVisibility(View.GONE);
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);
}
}
}

View file

@ -65,11 +65,11 @@ class SearchImagesRenderer extends Renderer<Media> {
*/
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);
}
}
}

View file

@ -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();
}

View file

@ -736,17 +736,21 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
@NonNull
public List<Media> searchImages(String query, int offset) {
List<CustomApiResult> imageNodes = null;
List<CustomApiResult> 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<Media> 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;
}