Skip to content

Commit 6f4c60b

Browse files
authored
With pause and resume for uploads (commons-app#3858)
* With pause and resume for uploads * Dispose current upload * Make pause and resume work * Check stash validity * With java docs * minor
1 parent e40e969 commit 6f4c60b

27 files changed

+484
-156
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package fr.free.nrw.commons.contributions
2+
3+
import android.os.Parcel
4+
import android.os.Parcelable
5+
import fr.free.nrw.commons.upload.UploadResult
6+
import kotlinx.android.parcel.Parcelize
7+
8+
data class ChunkInfo(
9+
val uploadResult: UploadResult,
10+
val lastChunkIndex: Int
11+
) : Parcelable {
12+
constructor(parcel: Parcel) : this(
13+
parcel.readParcelable(UploadResult::class.java.classLoader),
14+
parcel.readInt()
15+
) {
16+
}
17+
18+
override fun writeToParcel(parcel: Parcel, flags: Int) {
19+
parcel.writeParcelable(uploadResult, flags)
20+
parcel.writeInt(lastChunkIndex)
21+
}
22+
23+
override fun describeContents(): Int {
24+
return 0
25+
}
26+
27+
companion object CREATOR : Parcelable.Creator<ChunkInfo> {
28+
override fun createFromParcel(parcel: Parcel): ChunkInfo {
29+
return ChunkInfo(parcel)
30+
}
31+
32+
override fun newArray(size: Int): Array<ChunkInfo?> {
33+
return arrayOfNulls(size)
34+
}
35+
}
36+
}

app/src/main/java/fr/free/nrw/commons/contributions/Contribution.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ data class Contribution constructor(
2525
val decimalCoords: String? = null,
2626
var dateCreatedSource: String? = null,
2727
var wikidataPlace: WikidataPlace? = null,
28+
var chunkInfo: ChunkInfo? = null,
2829
/**
2930
* @return array list of entityids for the depictions
3031
*/
@@ -36,7 +37,8 @@ data class Contribution constructor(
3637
var mimeType: String? = null,
3738
val localUri: Uri? = null,
3839
var dataLength: Long = 0,
39-
var dateCreated: Date? = null
40+
var dateCreated: Date? = null,
41+
var dateModified: Date? = null
4042
) : Parcelable {
4143

4244
fun completeWith(media: Media): Contribution {
@@ -68,6 +70,7 @@ data class Contribution constructor(
6870
const val STATE_FAILED = 1
6971
const val STATE_QUEUED = 2
7072
const val STATE_IN_PROGRESS = 3
73+
const val STATE_PAUSED = 4
7174

7275
/**
7376
* Formatting captions to the Wikibase format for sending labels

app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import androidx.room.Update;
1111
import io.reactivex.Completable;
1212
import io.reactivex.Single;
13+
import java.util.Calendar;
14+
import java.util.Date;
1315
import java.util.List;
1416

1517
@Dao
@@ -23,7 +25,10 @@ public abstract class ContributionDao {
2325

2426
public Completable save(final Contribution contribution) {
2527
return Completable
26-
.fromAction(() -> saveSynchronous(contribution));
28+
.fromAction(() -> {
29+
contribution.setDateModified(Calendar.getInstance().getTime());
30+
saveSynchronous(contribution);
31+
});
2732
}
2833

2934
@Transaction
@@ -67,6 +72,9 @@ public Completable delete(final Contribution contribution) {
6772

6873
public Completable update(final Contribution contribution) {
6974
return Completable
70-
.fromAction(() -> updateSynchronous(contribution));
75+
.fromAction(() -> {
76+
contribution.setDateModified(Calendar.getInstance().getTime());
77+
updateSynchronous(contribution);
78+
});
7179
}
7280
}

app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java

+50-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public class ContributionViewHolder extends RecyclerView.ViewHolder {
4343
ImageButton retryButton;
4444
@BindView(R.id.cancelButton)
4545
ImageButton cancelButton;
46+
@BindView(R.id.pauseResumeButton)
47+
ImageButton pauseResumeButton;
4648

4749

4850
private int position;
@@ -93,7 +95,11 @@ public void init(final int position, final Contribution contribution) {
9395
case Contribution.STATE_IN_PROGRESS:
9496
stateView.setVisibility(View.GONE);
9597
progressView.setVisibility(View.VISIBLE);
96-
imageOptions.setVisibility(View.GONE);
98+
addToWikipediaButton.setVisibility(View.GONE);
99+
pauseResumeButton.setVisibility(View.VISIBLE);
100+
cancelButton.setVisibility(View.GONE);
101+
retryButton.setVisibility(View.GONE);
102+
imageOptions.setVisibility(View.VISIBLE);
97103
final long total = contribution.getDataLength();
98104
final long transferred = contribution.getTransferred();
99105
if (transferred == 0 || transferred >= total) {
@@ -102,10 +108,23 @@ public void init(final int position, final Contribution contribution) {
102108
progressView.setProgress((int) (((double) transferred / (double) total) * 100));
103109
}
104110
break;
111+
case Contribution.STATE_PAUSED:
112+
stateView.setVisibility(View.VISIBLE);
113+
stateView.setText(R.string.paused);
114+
setResume();
115+
progressView.setVisibility(View.GONE);
116+
cancelButton.setVisibility(View.GONE);
117+
retryButton.setVisibility(View.GONE);
118+
pauseResumeButton.setVisibility(View.VISIBLE);
119+
imageOptions.setVisibility(View.VISIBLE);
120+
break;
105121
case Contribution.STATE_FAILED:
106122
stateView.setVisibility(View.VISIBLE);
107123
stateView.setText(R.string.contribution_state_failed);
108124
progressView.setVisibility(View.GONE);
125+
cancelButton.setVisibility(View.VISIBLE);
126+
retryButton.setVisibility(View.VISIBLE);
127+
pauseResumeButton.setVisibility(View.GONE);
109128
imageOptions.setVisibility(View.VISIBLE);
110129
break;
111130
}
@@ -187,4 +206,34 @@ public void imageClicked() {
187206
public void wikipediaButtonClicked() {
188207
callback.addImageToWikipedia(contribution);
189208
}
209+
210+
/**
211+
* Triggers a callback for pause/resume
212+
*/
213+
@OnClick(R.id.pauseResumeButton)
214+
public void onPauseResumeButtonClicked() {
215+
if (pauseResumeButton.getTag().toString().equals("pause")) {
216+
callback.pauseUpload(contribution);
217+
setResume();
218+
} else {
219+
callback.resumeUpload(contribution);
220+
setPaused();
221+
}
222+
}
223+
224+
/**
225+
* Update pause/resume button to show pause state
226+
*/
227+
private void setPaused() {
228+
pauseResumeButton.setImageResource(R.drawable.pause_icon);
229+
pauseResumeButton.setTag(R.string.pause);
230+
}
231+
232+
/**
233+
* Update pause/resume button to show resume state
234+
*/
235+
private void setResume() {
236+
pauseResumeButton.setImageResource(R.drawable.play_icon);
237+
pauseResumeButton.setTag(R.string.resume);
238+
}
190239
}

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.free.nrw.commons.contributions;
22

33
import static fr.free.nrw.commons.contributions.Contribution.STATE_FAILED;
4+
import static fr.free.nrw.commons.contributions.Contribution.STATE_PAUSED;
45
import static fr.free.nrw.commons.contributions.MainActivity.CONTRIBUTIONS_TAB_POSITION;
56
import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween;
67

@@ -454,7 +455,7 @@ private void fetchCampaigns() {
454455
@Override
455456
public void retryUpload(Contribution contribution) {
456457
if (NetworkUtils.isInternetConnectionEstablished(getContext())) {
457-
if (contribution.getState() == STATE_FAILED && null != uploadService) {
458+
if (contribution.getState() == STATE_FAILED || contribution.getState() == STATE_PAUSED && null != uploadService) {
458459
uploadService.queue(contribution);
459460
Timber.d("Restarting for %s", contribution.toString());
460461
} else {
@@ -466,6 +467,15 @@ public void retryUpload(Contribution contribution) {
466467

467468
}
468469

470+
/**
471+
* Pauses the upload
472+
* @param contribution
473+
*/
474+
@Override
475+
public void pauseUpload(Contribution contribution) {
476+
uploadService.pauseUpload(contribution);
477+
}
478+
469479
/**
470480
* Replace whatever is in the current contributionsFragmentContainer view with
471481
* mediaDetailPagerFragment, and preserve previous state in back stack. Called when user selects a

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java

+4
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,9 @@ public interface Callback {
7878
void openMediaDetail(int contribution);
7979

8080
void addImageToWikipedia(Contribution contribution);
81+
82+
void pauseUpload(Contribution contribution);
83+
84+
void resumeUpload(Contribution contribution);
8185
}
8286
}

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java

+25
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import javax.inject.Inject;
3737
import javax.inject.Named;
3838
import org.wikipedia.dataclient.WikiSite;
39+
import timber.log.Timber;
3940

4041
/**
4142
* Created by root on 01.06.2018.
@@ -90,6 +91,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
9091
private final int SPAN_COUNT_PORTRAIT = 1;
9192

9293

94+
@Override
9395
public View onCreateView(
9496
final LayoutInflater inflater, @Nullable final ViewGroup container,
9597
@Nullable final Bundle savedInstanceState) {
@@ -192,6 +194,7 @@ private void animateFAB(final boolean isFabOpen) {
192194
/**
193195
* Shows welcome message if user has no contributions yet i.e. new user.
194196
*/
197+
@Override
195198
public void showWelcomeTip(final boolean shouldShow) {
196199
noContributionsYet.setVisibility(shouldShow ? VISIBLE : GONE);
197200
}
@@ -201,10 +204,12 @@ public void showWelcomeTip(final boolean shouldShow) {
201204
*
202205
* @param shouldShow True when contributions list should be hidden.
203206
*/
207+
@Override
204208
public void showProgress(final boolean shouldShow) {
205209
progressBar.setVisibility(shouldShow ? VISIBLE : GONE);
206210
}
207211

212+
@Override
208213
public void showNoContributionsUI(final boolean shouldShow) {
209214
noContributionsYet.setVisibility(shouldShow ? VISIBLE : GONE);
210215
}
@@ -263,6 +268,24 @@ public void addImageToWikipedia(Contribution contribution) {
263268
});
264269
}
265270

271+
/**
272+
* Pauses the current upload
273+
* @param contribution
274+
*/
275+
@Override
276+
public void pauseUpload(Contribution contribution) {
277+
callback.pauseUpload(contribution);
278+
}
279+
280+
/**
281+
* Resumes the current upload
282+
* @param contribution
283+
*/
284+
@Override
285+
public void resumeUpload(Contribution contribution) {
286+
callback.retryUpload(contribution);
287+
}
288+
266289
/**
267290
* Display confirmation dialog with instructions when the user tries to add image to wikipedia
268291
*
@@ -311,6 +334,8 @@ public interface Callback {
311334

312335
void retryUpload(Contribution contribution);
313336

337+
void pauseUpload(Contribution contribution);
338+
314339
void showDetail(int position);
315340
}
316341
}

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import androidx.paging.DataSource.Factory;
44
import io.reactivex.Completable;
55
import java.util.ArrayList;
6+
import java.util.Date;
67
import java.util.List;
78

89
import javax.inject.Inject;

app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import fr.free.nrw.commons.contributions.ContributionDao
1010
* The database for accessing the respective DAOs
1111
*
1212
*/
13-
@Database(entities = [Contribution::class], version = 4, exportSchema = false)
13+
@Database(entities = [Contribution::class], version = 5, exportSchema = false)
1414
@TypeConverters(Converters::class)
1515
abstract class AppDatabase : RoomDatabase() {
1616
abstract fun contributionDao(): ContributionDao

app/src/main/java/fr/free/nrw/commons/db/Converters.java

+11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.google.gson.Gson;
66
import com.google.gson.reflect.TypeToken;
77
import fr.free.nrw.commons.CommonsApplication;
8+
import fr.free.nrw.commons.contributions.ChunkInfo;
89
import fr.free.nrw.commons.di.ApplicationlessInjection;
910
import fr.free.nrw.commons.location.LatLng;
1011
import fr.free.nrw.commons.upload.WikidataPlace;
@@ -82,6 +83,16 @@ public static WikidataPlace stringToWikidataPlace(String wikidataPlace) {
8283
return readObjectFromString(wikidataPlace, WikidataPlace.class);
8384
}
8485

86+
@TypeConverter
87+
public static String chunkInfoToString(ChunkInfo chunkInfo) {
88+
return writeObjectToString(chunkInfo);
89+
}
90+
91+
@TypeConverter
92+
public static ChunkInfo stringToChunkInfo(String chunkInfo) {
93+
return readObjectFromString(chunkInfo, ChunkInfo.class);
94+
}
95+
8596
@TypeConverter
8697
public static String depictionListToString(List<DepictedItem> depictedItems) {
8798
return writeObjectToString(depictedItems);

app/src/main/java/fr/free/nrw/commons/upload/CountingRequestBody.kt

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fr.free.nrw.commons.upload
22

3+
import fr.free.nrw.commons.contributions.ChunkInfo
34
import okhttp3.MediaType
45
import okhttp3.RequestBody
56
import okio.*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package fr.free.nrw.commons.upload
2+
3+
data class StashUploadResult(
4+
val state: StashUploadState,
5+
val fileKey: String?
6+
)
7+
8+
enum class StashUploadState {
9+
SUCCESS,
10+
PAUSED,
11+
FAILED
12+
}

0 commit comments

Comments
 (0)