diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java index 3dc79a50b..df50b9cb8 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java @@ -1,6 +1,8 @@ package fr.free.nrw.commons.contributions; import android.view.View; +import android.widget.Button; +import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.TextView; @@ -13,6 +15,9 @@ class ContributionViewHolder { final TextView stateView; final TextView seqNumView; final ProgressBar progressView; + final ImageButton retryButton; + final ImageButton cancelButton; + int position; ContributionViewHolder(View parent) { imageView = parent.findViewById(R.id.contributionImage); @@ -20,5 +25,8 @@ class ContributionViewHolder { stateView = parent.findViewById(R.id.contributionState); seqNumView = parent.findViewById(R.id.contributionSequenceNumber); progressView = parent.findViewById(R.id.contributionProgress); + retryButton = parent.findViewById(R.id.retryButton); + cancelButton = parent.findViewById(R.id.cancelButton); + position = 0; } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java index 8b43c9f90..fa1d82ae4 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java @@ -332,6 +332,8 @@ public class ContributionsFragment contributionsListFragment.clearSyncMessage(); notifyAndMigrateDataSetObservers(); + + ((ContributionsListAdapter)contributionsListFragment.getAdapter()).setUploadService(uploadService); } } @@ -421,36 +423,6 @@ public class ContributionsFragment mediaDetailPagerFragment.showImage(i); } - /** - * Retry upload when it is failed - * @param i position of upload which will be retried - */ - public void retryUpload(int i) { - allContributions.moveToPosition(i); - Contribution c = contributionDao.fromCursor(allContributions); - if (c.getState() == STATE_FAILED) { - uploadService.queue(UploadService.ACTION_UPLOAD_FILE, c); - Timber.d("Restarting for %s", c.toString()); - } else { - Timber.d("Skipping re-upload for non-failed %s", c.toString()); - } - } - - /** - * Delete a failed upload attempt - * @param i position of upload attempt which will be deteled - */ - public void deleteUpload(int i) { - allContributions.moveToPosition(i); - Contribution c = contributionDao.fromCursor(allContributions); - if (c.getState() == STATE_FAILED) { - Timber.d("Deleting failed contrib %s", c.toString()); - contributionDao.delete(c); - } else { - Timber.d("Skipping deletion for non-failed contrib %s", c.toString()); - } - } - @Override public void refreshSource() { getActivity().getSupportLoaderManager().restartLoader(0, null, this); diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java index a31caf54f..e26599cbc 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java @@ -3,21 +3,33 @@ package fr.free.nrw.commons.contributions; import android.content.Context; import android.database.Cursor; import android.support.v4.widget.CursorAdapter; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import fr.free.nrw.commons.R; +import fr.free.nrw.commons.upload.UploadService; +import fr.free.nrw.commons.utils.NetworkUtils; +import fr.free.nrw.commons.utils.ViewUtil; +import timber.log.Timber; + +import static fr.free.nrw.commons.contributions.Contribution.STATE_FAILED; class ContributionsListAdapter extends CursorAdapter { private final ContributionDao contributionDao; + private UploadService uploadService; public ContributionsListAdapter(Context context, Cursor c, int flags, ContributionDao contributionDao) { super(context, c, flags); this.contributionDao = contributionDao; } + public void setUploadService( UploadService uploadService) { + this.uploadService = uploadService; + } + @Override public View newView(Context context, Cursor cursor, ViewGroup viewGroup) { View parent = LayoutInflater.from(context) @@ -36,21 +48,29 @@ class ContributionsListAdapter extends CursorAdapter { views.seqNumView.setText(String.valueOf(cursor.getPosition() + 1)); views.seqNumView.setVisibility(View.VISIBLE); + views.position = cursor.getPosition(); + switch (contribution.getState()) { case Contribution.STATE_COMPLETED: views.stateView.setVisibility(View.GONE); views.progressView.setVisibility(View.GONE); + views.retryButton.setVisibility(View.GONE); + views.cancelButton.setVisibility(View.GONE); views.stateView.setText(""); break; case Contribution.STATE_QUEUED: views.stateView.setVisibility(View.VISIBLE); views.progressView.setVisibility(View.GONE); views.stateView.setText(R.string.contribution_state_queued); + views.retryButton.setVisibility(View.GONE); + views.cancelButton.setVisibility(View.GONE); break; case Contribution.STATE_IN_PROGRESS: views.stateView.setVisibility(View.GONE); views.progressView.setVisibility(View.VISIBLE); + views.retryButton.setVisibility(View.GONE); + views.cancelButton.setVisibility(View.GONE); long total = contribution.getDataLength(); long transferred = contribution.getTransferred(); if (transferred == 0 || transferred >= total) { @@ -63,7 +83,63 @@ class ContributionsListAdapter extends CursorAdapter { views.stateView.setVisibility(View.VISIBLE); views.stateView.setText(R.string.contribution_state_failed); views.progressView.setVisibility(View.GONE); + views.retryButton.setVisibility(View.VISIBLE); + views.cancelButton.setVisibility(View.VISIBLE); + + views.retryButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + retryUpload(cursor); + } + }); + + views.cancelButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + deleteUpload(cursor); + } + }); + + break; } } + + /** + * Retry upload when it is failed + * @param cursor cursor will be retried + */ + public void retryUpload(Cursor cursor) { + if (NetworkUtils.isInternetConnectionEstablished(mContext)) { + Contribution c = contributionDao.fromCursor(cursor); + if (c.getState() == STATE_FAILED) { + uploadService.queue(UploadService.ACTION_UPLOAD_FILE, c); + Timber.d("Restarting for %s", c.toString()); + } else { + Timber.d("Skipping re-upload for non-failed %s", c.toString()); + } + } else { + ViewUtil.showLongToast(mContext,R.string.this_function_needs_network_connection); + } + + } + + /** + * Delete a failed upload attempt + * @param cursor cursor which will be deleted + */ + public void deleteUpload(Cursor cursor) { + if (NetworkUtils.isInternetConnectionEstablished(mContext)) { + Contribution c = contributionDao.fromCursor(cursor); + if (c.getState() == STATE_FAILED) { + Timber.d("Deleting failed contrib %s", c.toString()); + contributionDao.delete(c); + } else { + Timber.d("Skipping deletion for non-failed contrib %s", c.toString()); + } + } else { + ViewUtil.showLongToast(mContext,R.string.this_function_needs_network_connection); + } + + } } 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 76549b207..5b1004be9 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 @@ -189,16 +189,6 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple // Set wallpaper setWallpaper(m); return true; - case R.id.menu_retry_current_image: - // Retry - //((MainActivity) getActivity()).retryUpload(pager.getCurrentItem()); - getActivity().getSupportFragmentManager().popBackStack(); - return true; - case R.id.menu_cancel_current_image: - // todo: delete image - //((MainActivity) getActivity()).deleteUpload(pager.getCurrentItem()); - getActivity().getSupportFragmentManager().popBackStack(); - return true; default: return super.onOptionsItemSelected(item); } @@ -279,8 +269,6 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple Media m = provider.getMediaAtPosition(pager.getCurrentItem()); if (m != null) { // Enable default set of actions, then re-enable different set of actions only if it is a failed contrib - menu.findItem(R.id.menu_retry_current_image).setEnabled(false).setVisible(false); - menu.findItem(R.id.menu_cancel_current_image).setEnabled(false).setVisible(false); menu.findItem(R.id.menu_browser_current_image).setEnabled(true).setVisible(true); menu.findItem(R.id.menu_share_current_image).setEnabled(true).setVisible(true); menu.findItem(R.id.menu_download_current_image).setEnabled(true).setVisible(true); @@ -297,8 +285,6 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple Contribution c = (Contribution) m; switch (c.getState()) { case Contribution.STATE_FAILED: - menu.findItem(R.id.menu_retry_current_image).setEnabled(true).setVisible(true); - menu.findItem(R.id.menu_cancel_current_image).setEnabled(true).setVisible(true); menu.findItem(R.id.menu_browser_current_image).setEnabled(false).setVisible(false); menu.findItem(R.id.menu_share_current_image).setEnabled(false).setVisible(false); menu.findItem(R.id.menu_download_current_image).setEnabled(false).setVisible(false); @@ -306,8 +292,6 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple break; case Contribution.STATE_IN_PROGRESS: case Contribution.STATE_QUEUED: - menu.findItem(R.id.menu_retry_current_image).setEnabled(false).setVisible(false); - menu.findItem(R.id.menu_cancel_current_image).setEnabled(false).setVisible(false); menu.findItem(R.id.menu_browser_current_image).setEnabled(false).setVisible(false); menu.findItem(R.id.menu_share_current_image).setEnabled(false).setVisible(false); menu.findItem(R.id.menu_download_current_image).setEnabled(false).setVisible(false); 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 8c4c39639..ed56e1c77 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 @@ -8,6 +8,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; +import android.util.Log; import com.google.gson.Gson; @@ -44,6 +45,7 @@ import java.util.concurrent.Callable; import fr.free.nrw.commons.BuildConfig; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.PageTitle; +import fr.free.nrw.commons.R; import fr.free.nrw.commons.achievements.FeedbackResponse; import fr.free.nrw.commons.auth.AccountUtil; import fr.free.nrw.commons.category.CategoryImageUtils; @@ -52,6 +54,7 @@ import fr.free.nrw.commons.notification.Notification; import fr.free.nrw.commons.notification.NotificationUtils; import fr.free.nrw.commons.utils.ContributionUtils; import fr.free.nrw.commons.utils.DateUtils; +import fr.free.nrw.commons.utils.ViewUtil; import in.yuvi.http.fluent.Http; import io.reactivex.Observable; import io.reactivex.Single; @@ -81,6 +84,8 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { private final String WIKIMEDIA_CAMPAIGNS_BASE_URL = "https://raw.githubusercontent.com/commons-app/campaigns/master/campaigns.json"; + private final String ERROR_CODE_BAD_TOKEN = "badtoken"; + public ApacheHttpClientMediaWikiApi(Context context, String apiURL, String wikidatApiURL, @@ -901,6 +906,10 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { if (!resultStatus.equals("Success")) { String errorCode = result.getString("/api/error/@code"); Timber.e(errorCode); + + if (errorCode.equals(ERROR_CODE_BAD_TOKEN)) { + ViewUtil.showLongToast(context, R.string.bad_token_error_proposed_solution); + } return new UploadResult(resultStatus, errorCode); } else { // If success we have to remove file from temp directory diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java index 0873d46d8..f4a624b18 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java @@ -10,6 +10,7 @@ import android.content.Intent; import android.graphics.BitmapFactory; import android.os.Bundle; import android.support.v4.app.NotificationCompat; +import android.util.Log; import android.webkit.MimeTypeMap; import android.widget.Toast; diff --git a/app/src/main/res/drawable-hdpi/ic_cancel_white.png b/app/src/main/res/drawable-hdpi/ic_cancel_white.png new file mode 100644 index 000000000..f8709859d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_cancel_white.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_retry_white.png b/app/src/main/res/drawable-hdpi/ic_retry_white.png new file mode 100644 index 000000000..7664cb010 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_retry_white.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_cancel_white.png b/app/src/main/res/drawable-mdpi/ic_cancel_white.png new file mode 100644 index 000000000..2d693927f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_cancel_white.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_retry_white.png b/app/src/main/res/drawable-mdpi/ic_retry_white.png new file mode 100644 index 000000000..b251e128a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_retry_white.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_cancel_white.png b/app/src/main/res/drawable-xhdpi/ic_cancel_white.png new file mode 100644 index 000000000..495fed7ac Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_cancel_white.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_retry_white.png b/app/src/main/res/drawable-xhdpi/ic_retry_white.png new file mode 100644 index 000000000..8526afbda Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_retry_white.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_cancel_white.png b/app/src/main/res/drawable-xxhdpi/ic_cancel_white.png new file mode 100644 index 000000000..8c4acd524 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_cancel_white.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_retry_white.png b/app/src/main/res/drawable-xxhdpi/ic_retry_white.png new file mode 100644 index 000000000..3ad498281 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_retry_white.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_cancel_white.png b/app/src/main/res/drawable-xxxhdpi/ic_cancel_white.png new file mode 100644 index 000000000..8f131ab24 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_cancel_white.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_retry_white.png b/app/src/main/res/drawable-xxxhdpi/ic_retry_white.png new file mode 100644 index 000000000..96046e169 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_retry_white.png differ diff --git a/app/src/main/res/layout/layout_contribution.xml b/app/src/main/res/layout/layout_contribution.xml index b8237b1c2..be9579a02 100644 --- a/app/src/main/res/layout/layout_contribution.xml +++ b/app/src/main/res/layout/layout_contribution.xml @@ -28,39 +28,83 @@ - - + android:layout_weight="3" + android:layout_gravity="center|bottom" + android:orientation="vertical" + android:padding="@dimen/small_gap" + > + - + + + + + + + android:layout_weight="1" + android:orientation="horizontal" + android:padding="@dimen/small_gap" + > + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/fragment_image_detail.xml b/app/src/main/res/menu/fragment_image_detail.xml index 3161bd155..21f5f9be9 100644 --- a/app/src/main/res/menu/fragment_image_detail.xml +++ b/app/src/main/res/menu/fragment_image_detail.xml @@ -25,18 +25,5 @@ android:id="@+id/menu_set_as_wallpaper" android:title="@string/menu_set_wallpaper" app:showAsAction="never" /> - - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 06025e255..653a91450 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -442,4 +442,7 @@ Upload your first media by touching the camera or gallery icon above. Tap here to see the ongoing campaigns You won\'t see the campaigns anymore. However, you can re-enable this notification in Settings if you wish. + This function requires network connection, please check your connection settings. + Upload failed due to issues with edit token. Please try logging out and in again. +