Skip to content

Limit number of images uploaded at a time #3124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import android.net.Uri;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;

Expand All @@ -17,6 +19,8 @@
import com.facebook.drawee.view.SimpleDraweeView;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.filepicker.UploadableFile;
import timber.log.Timber;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -61,18 +65,20 @@ public int getItemCount() {
return uploadableFiles.size();
}

public class ViewHolder extends RecyclerView.ViewHolder {

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
@BindView(R.id.rl_container)
RelativeLayout rlContainer;
@BindView(R.id.iv_thumbnail)
SimpleDraweeView background;
@BindView(R.id.iv_error)
ImageView ivError;
@BindView(R.id.iv_close)
ImageButton ivClose;

public ViewHolder(@NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
ivClose.setOnClickListener(this);
}

/**
Expand All @@ -84,29 +90,47 @@ public void bind(int position) {
Uri uri = uploadableFile.getMediaUri();
background.setImageURI(Uri.fromFile(new File(String.valueOf(uri))));

// Timber.e("Current position : "+position+" Current selected file position : "+callback.getCurrentSelectedFilePosition());

if (position == callback.getCurrentSelectedFilePosition()) {
rlContainer.setEnabled(true);
rlContainer.setClickable(true);
rlContainer.setAlpha(1.0f);
background.setAlpha(1.0f);
ivError.setAlpha(1.0f);
ivClose.setAlpha(1.0f);
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
rlContainer.setElevation(10);
background.setElevation(10);
}
} else {
rlContainer.setEnabled(false);
rlContainer.setClickable(false);
rlContainer.setAlpha(0.5f);
background.setAlpha(0.5f); //once an image is deleted the newly bound image will not have faded effect if rlContainer is used
ivError.setAlpha(0.5f);
ivClose.setAlpha(0.5f);
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
rlContainer.setElevation(0);
background.setElevation(0);
}
}
}

@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.iv_close:
removeImageAt(getAdapterPosition());
break;
}
}
}

private void removeImageAt(int position) {
notifyItemRemoved(position);
}

/**
* Callback used to get the current selected file position
*/
interface Callback {

int getCurrentSelectedFilePosition();
}
}
81 changes: 77 additions & 4 deletions app/src/main/java/fr/free/nrw/commons/upload/UploadActivity.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package fr.free.nrw.commons.upload;

import static fr.free.nrw.commons.contributions.ContributionController.ACTION_INTERNAL_UPLOADS;
import static fr.free.nrw.commons.upload.UploadPresenter.MAX_NO_OF_IMAGES;
import static fr.free.nrw.commons.upload.UploadService.EXTRA_FILES;
import static fr.free.nrw.commons.wikidata.WikidataConstants.PLACE_OBJECT;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
Expand All @@ -20,6 +22,7 @@
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;

import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
Expand Down Expand Up @@ -84,6 +87,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View
@BindView(R.id.vp_upload)
ViewPager vpUpload;

@BindView(R.id.tv_err_icon)
ImageButton tvErrorIcon;

private boolean isTitleExpanded=true;

private CompositeDisposable compositeDisposable;
Expand All @@ -99,6 +105,7 @@ public class UploadActivity extends BaseActivity implements UploadContract.View
private Place place;
private List<UploadableFile> uploadableFiles= Collections.emptyList();
private int currentSelectedPosition=0;
private boolean mediaDeleteHandled = false; //this flag is used to avoid image delete loop

@SuppressLint("CheckResult")
@Override
Expand Down Expand Up @@ -135,7 +142,20 @@ private void initThumbnailsRecyclerView() {
LinearLayoutManager.HORIZONTAL, false));
thumbnailsAdapter=new ThumbnailsAdapter(() -> currentSelectedPosition);
rvThumbnails.setAdapter(thumbnailsAdapter);

RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManagerWrapper(this, LinearLayoutManager.HORIZONTAL, false);
rvThumbnails.setLayoutManager(mLayoutManager);
thumbnailsAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
if(mediaDeleteHandled){
mediaDeleteHandled = false;
return;
}
mediaDeleteHandled = true;
super.onItemRangeRemoved(positionStart, itemCount);
presenter.deletePictureAtIndex(positionStart);
}
});
}

private void initViewPager() {
Expand Down Expand Up @@ -243,8 +263,28 @@ public void showHideTopCard(boolean shouldShow) {
public void onUploadMediaDeleted(int index) {
fragments.remove(index);//Remove the corresponding fragment
uploadableFiles.remove(index);//Remove the files from the list
thumbnailsAdapter.notifyItemRemoved(index); //Notify the thumbnails adapter

if(mediaDeleteHandled){
mediaDeleteHandled = false;
}else{
thumbnailsAdapter.notifyItemRemoved(index); //Notify the thumbnails adapter
mediaDeleteHandled = true;
}

if (fragments.size()<= MAX_NO_OF_IMAGES+2){ //if number of images is less than or equal
UploadMediaDetailFragment.setTooManyImages(false); //to max no of images allowed hide error icon
tvErrorIcon.setVisibility(View.GONE); //and set too nay images flag to false.
}

uploadImagesAdapter.notifyDataSetChanged(); //Notify the ViewPager

if(currentSelectedPosition == index || currentSelectedPosition == uploadableFiles.size()){ //if the current viewing image is deleted
if(currentSelectedPosition>=uploadableFiles.size()){ //or any image is deleted while viewing last
currentSelectedPosition--; //image the the current selected position should
} //be decremented.
vpUpload.setCurrentItem(currentSelectedPosition,true);
thumbnailsAdapter.notifyDataSetChanged(); //this line is needed to set alpha to 1.0 of current thumbnail
}
}

@Override
Expand Down Expand Up @@ -283,9 +323,12 @@ private void receiveSharedItems() {
handleNullMedia();
} else {
//Show thumbnails
if (uploadableFiles.size()
> 1) {//If there is only file, no need to show the image thumbnails
if (uploadableFiles.size() > 1) {//If there is only file, no need to show the image thumbnails
thumbnailsAdapter.setUploadableFiles(uploadableFiles);
if(uploadableFiles.size()>MAX_NO_OF_IMAGES){
UploadMediaDetailFragment.setTooManyImages(true);
tvErrorIcon.setVisibility(View.VISIBLE);
}
} else {
llContainerTopCard.setVisibility(View.GONE);
}
Expand Down Expand Up @@ -330,6 +373,7 @@ public int getTotalNumberOfSteps() {
fragments.add(uploadMediaDetailFragment);
}


uploadCategoriesFragment = new UploadCategoriesFragment();
uploadCategoriesFragment.setCallback(this);

Expand Down Expand Up @@ -448,6 +492,15 @@ public void onRlContainerTitleClicked(){
ibToggleTopCard.setRotation(ibToggleTopCard.getRotation() + 180);
}

@OnClick(R.id.tv_err_icon)
public void onTvErrorIconClicked(){
new android.app.AlertDialog.Builder(UploadActivity.this).setTitle(R.string.upload_too_many_images_title).setMessage(getString(R.string.upload_too_many_images_message,MAX_NO_OF_IMAGES,uploadableFiles.size()-MAX_NO_OF_IMAGES))
.setCancelable(true)
.setPositiveButton(android.R.string.ok, (dialog, id) -> dialog.cancel())
.create()
.show();
}

@Override
protected void onDestroy() {
super.onDestroy();
Expand All @@ -456,4 +509,24 @@ protected void onDestroy() {
mediaLicenseFragment.setCallback(null);
uploadCategoriesFragment.setCallback(null);
}

public class LinearLayoutManagerWrapper extends LinearLayoutManager {

public LinearLayoutManagerWrapper(Context context) {
super(context);
}

public LinearLayoutManagerWrapper(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}

public LinearLayoutManagerWrapper(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}

@Override
public boolean supportsPredictiveItemAnimations() {
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class UploadPresenter implements UploadContract.UserActionListener {
new Class[]{UploadContract.View.class}, (proxy, method, methodArgs) -> null);
private final UploadRepository repository;
private UploadContract.View view = DUMMY;
public final static int MAX_NO_OF_IMAGES = 5;

private CompositeDisposable compositeDisposable;

Expand Down Expand Up @@ -89,11 +90,13 @@ public void onComplete() {
@Override
public void deletePictureAtIndex(int index) {
List<UploadableFile> uploadableFiles = view.getUploadableFiles();
if (index == uploadableFiles.size() - 1) {//If the next fragment to be shown is not one of the MediaDetailsFragment, lets hide the top card
view.showHideTopCard(false);
}
//Ask the repository to delete the picture
repository.deletePicture(uploadableFiles.get(index).getFilePath());
try {
repository.deletePicture(uploadableFiles.get(index).getFilePath());
}catch (IndexOutOfBoundsException e){
Timber.e("Image index %d is out of bound",index);
return;
}
if (uploadableFiles.size() == 1) {
view.showMessage(R.string.upload_cancelled);
view.finish();
Expand Down
Loading