Skip to content

Commit ee7af37

Browse files
whymmaskaravivek
authored andcommitted
Stash upload (commons-app#2505)
* Introduce Single<UploadResult> * Two stage upload process - split upload process and use stash - resolve filename conflict after upload not before - use NotificationManagerCompat; add notification tag; assign temporaty stash file name
1 parent 341f961 commit ee7af37

File tree

5 files changed

+212
-71
lines changed

5 files changed

+212
-71
lines changed

app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java

+53-23
Original file line numberDiff line numberDiff line change
@@ -853,35 +853,65 @@ public boolean logEvents(LogBuilder[] logBuilders) {
853853

854854
@Override
855855
@NonNull
856-
public UploadResult uploadFile(String filename,
857-
@NonNull InputStream file,
858-
long dataLength,
859-
String pageContents,
860-
String editSummary,
861-
Uri fileUri,
862-
Uri contentProviderUri,
863-
final ProgressListener progressListener) throws IOException {
856+
public Single<UploadStash> uploadFile(
857+
String filename,
858+
@NonNull InputStream file,
859+
long dataLength,
860+
Uri fileUri,
861+
Uri contentProviderUri,
862+
ProgressListener progressListener) throws IOException {
863+
return Single.fromCallable(() -> {
864+
CustomApiResult result = api.uploadToStash(filename, file, dataLength, getEditToken(), progressListener::onProgress);
865+
866+
Timber.wtf("Result: " + result.toString());
867+
868+
String resultStatus = result.getString("/api/upload/@result");
869+
if (!resultStatus.equals("Success")) {
870+
String errorCode = result.getString("/api/error/@code");
871+
Timber.e(errorCode);
872+
873+
if (errorCode.equals(ERROR_CODE_BAD_TOKEN)) {
874+
ViewUtil.showLongToast(context, R.string.bad_token_error_proposed_solution);
875+
}
876+
return new UploadStash(errorCode, resultStatus, filename, "");
877+
} else {
878+
String filekey = result.getString("/api/upload/@filekey");
879+
return new UploadStash("", resultStatus, filename, filekey);
880+
}
881+
});
882+
}
864883

865-
CustomApiResult result = api.upload(filename, file, dataLength, pageContents, editSummary, getEditToken(), progressListener::onProgress);
866884

867-
Timber.d("Result: %s", result.toString());
885+
@Override
886+
@NonNull
887+
public Single<UploadResult> uploadFileFinalize(
888+
String filename,
889+
String filekey,
890+
String pageContents,
891+
String editSummary) throws IOException {
892+
return Single.fromCallable(() -> {
893+
CustomApiResult result = api.uploadFromStash(
894+
filename, filekey, pageContents, editSummary,
895+
getEditToken());
868896

869-
String resultStatus = result.getString("/api/upload/@result");
897+
Timber.d("Result: %s", result.toString());
870898

871-
if (!resultStatus.equals("Success")) {
872-
String errorCode = result.getString("/api/error/@code");
873-
Timber.e(errorCode);
899+
String resultStatus = result.getString("/api/upload/@result");
900+
if (!resultStatus.equals("Success")) {
901+
String errorCode = result.getString("/api/error/@code");
902+
Timber.e(errorCode);
874903

875-
if (errorCode.equals(ERROR_CODE_BAD_TOKEN)) {
876-
ViewUtil.showLongToast(context, R.string.bad_token_error_proposed_solution);
904+
if (errorCode.equals(ERROR_CODE_BAD_TOKEN)) {
905+
ViewUtil.showLongToast(context, R.string.bad_token_error_proposed_solution);
906+
}
907+
return new UploadResult(resultStatus, errorCode);
908+
} else {
909+
Date dateUploaded = parseMWDate(result.getString("/api/upload/imageinfo/@timestamp"));
910+
String canonicalFilename = "File:" + result.getString("/api/upload/@filename").replace("_", " "); // Title vs Filename
911+
String imageUrl = result.getString("/api/upload/imageinfo/@url");
912+
return new UploadResult(resultStatus, dateUploaded, canonicalFilename, imageUrl);
877913
}
878-
return new UploadResult(resultStatus, errorCode);
879-
} else {
880-
Date dateUploaded = parseMWDate(result.getString("/api/upload/imageinfo/@timestamp"));
881-
String canonicalFilename = "File:" + result.getString("/api/upload/@filename").replace("_", " "); // Title vs Filename
882-
String imageUrl = result.getString("/api/upload/imageinfo/@url");
883-
return new UploadResult(resultStatus, dateUploaded, canonicalFilename, imageUrl);
884-
}
914+
});
885915
}
886916

887917
/**

app/src/main/java/fr/free/nrw/commons/mwapi/CustomMwApi.java

+18-14
Original file line numberDiff line numberDiff line change
@@ -131,22 +131,13 @@ public String login(String username, String password) throws IOException {
131131
}
132132
}
133133

134-
public CustomApiResult upload(String filename, InputStream file, long length, String text, String comment, String token) throws IOException {
135-
return this.upload(filename, file, length, text, comment, token, null);
136-
}
137-
138-
public CustomApiResult upload(String filename, InputStream file, String text, String comment, String token) throws IOException {
139-
return this.upload(filename, file, -1, text, comment, token, null);
140-
}
141-
142-
public CustomApiResult upload(String filename, InputStream file, long length, String text, String comment, String token, ProgressListener uploadProgressListener) throws IOException {
143-
Timber.d("Initiating upload for file %s", filename);
144-
Http.HttpRequestBuilder builder = Http.multipart(apiURL)
134+
public CustomApiResult uploadToStash(String filename, InputStream file, long length, String token, ProgressListener uploadProgressListener) throws IOException {
135+
Timber.d("Initiating upload for file %s", filename);
136+
Http.HttpRequestBuilder builder = Http.multipart(apiURL)
145137
.data("action", "upload")
138+
.data("stash", "1")
146139
.data("token", token)
147-
.data("text", text)
148140
.data("ignorewarnings", "1")
149-
.data("comment", comment)
150141
.data("filename", filename)
151142
.sendProgressListener(uploadProgressListener);
152143
if (length != -1) {
@@ -155,7 +146,20 @@ public CustomApiResult upload(String filename, InputStream file, long length, St
155146
builder.file("file", filename, file);
156147
}
157148

158-
return CustomApiResult.fromRequestBuilder("uploadFile", builder, client);
149+
return CustomApiResult.fromRequestBuilder("uploadToStash", builder, client);
150+
}
151+
152+
public CustomApiResult uploadFromStash(String filename, String filekey, String text, String comment, String token) throws IOException {
153+
Http.HttpRequestBuilder builder = Http.multipart(apiURL)
154+
.data("action", "upload")
155+
.data("token", token)
156+
.data("ignorewarnings", "1")
157+
.data("text", text)
158+
.data("comment", comment)
159+
.data("filename", filename)
160+
.data("filekey", filekey);
161+
162+
return CustomApiResult.fromRequestBuilder("uploadFromStash", builder, client);
159163
}
160164

161165
public void logout() throws IOException {

app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import fr.free.nrw.commons.Media;
1212
import fr.free.nrw.commons.notification.Notification;
1313
import io.reactivex.Observable;
14+
import io.reactivex.Single;
1415

1516
public interface MediaWikiApi {
1617
String getUserAgent();
@@ -49,8 +50,13 @@ public interface MediaWikiApi {
4950
List<String> searchCategory(String title, int offset);
5051

5152
@NonNull
52-
UploadResult uploadFile(String filename, InputStream file, long dataLength, String pageContents, String editSummary, Uri fileUri, Uri contentProviderUri, ProgressListener progressListener) throws IOException;
53+
Single<UploadStash> uploadFile(String filename, InputStream file,
54+
long dataLength, Uri fileUri, Uri contentProviderUri,
55+
final ProgressListener progressListener) throws IOException;
5356

57+
@NonNull
58+
Single<UploadResult> uploadFileFinalize(String filename, String filekey,
59+
String pageContents, String editSummary) throws IOException;
5460
@Nullable
5561
String edit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
5662

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package fr.free.nrw.commons.mwapi;
2+
3+
import androidx.annotation.NonNull;
4+
import androidx.annotation.Nullable;
5+
6+
public class UploadStash {
7+
@NonNull
8+
private String errorCode;
9+
@NonNull
10+
private String resultStatus;
11+
@NonNull
12+
private String filename;
13+
@NonNull
14+
private String filekey;
15+
16+
@NonNull
17+
public final String getErrorCode() {
18+
return this.errorCode;
19+
}
20+
21+
@NonNull
22+
public final String getResultStatus() {
23+
return this.resultStatus;
24+
}
25+
26+
@NonNull
27+
public final String getFilename() {
28+
return this.filename;
29+
}
30+
31+
@NonNull
32+
public final String getFilekey() {
33+
return this.filekey;
34+
}
35+
36+
public UploadStash(@NonNull String errorCode, @NonNull String resultStatus, @NonNull String filename, @NonNull String filekey) {
37+
this.errorCode = errorCode;
38+
this.resultStatus = resultStatus;
39+
this.filename = filename;
40+
this.filekey = filekey;
41+
}
42+
43+
public String toString() {
44+
return "UploadStash(errorCode=" + this.errorCode + ", resultStatus=" + this.resultStatus + ", filename=" + this.filename + ", filekey=" + this.filekey + ")";
45+
}
46+
47+
public int hashCode() {
48+
return ((this.errorCode.hashCode() * 31 + this.resultStatus.hashCode()
49+
) * 31 + this.filename.hashCode()
50+
) * 31 + this.filekey.hashCode();
51+
}
52+
53+
public boolean equals(@Nullable Object obj) {
54+
if (this != obj) {
55+
if (obj instanceof UploadStash) {
56+
UploadStash that = (UploadStash)obj;
57+
if (this.errorCode.equals(that.errorCode)
58+
&& this.resultStatus.equals(that.resultStatus)
59+
&& this.filename.equals(that.filename)
60+
&& this.filekey.equals(that.filekey)) {
61+
return true;
62+
}
63+
}
64+
65+
return false;
66+
} else {
67+
return true;
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)