mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Bugfix/p18 uploads (#3869)
* updated gradle plugin version * BugFix #3856 * Do not use preference for deciding acceptable lat long for nearby uploads, instead save the corresponding location in the Contribution via UploadItem * Marshall contribution's hasInvalidLocation * reset un-related changes * Fixed test cases * Minor code formatting and docs
This commit is contained in:
parent
e471226405
commit
e7d93159d3
10 changed files with 67 additions and 33 deletions
|
|
@ -60,6 +60,19 @@ public class Contribution extends Media {
|
||||||
private String p18Value;
|
private String p18Value;
|
||||||
public Uri contentProviderUri;
|
public Uri contentProviderUri;
|
||||||
public String dateCreatedSource;
|
public String dateCreatedSource;
|
||||||
|
public int hasInvalidLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this true when ImageProcessor has said that the location is invalid
|
||||||
|
* @param hasInvalidLocation
|
||||||
|
*/
|
||||||
|
public void setHasInvalidLocation(boolean hasInvalidLocation) {
|
||||||
|
this.hasInvalidLocation = hasInvalidLocation ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHasInvalidLocation() {
|
||||||
|
return hasInvalidLocation == 1;
|
||||||
|
}
|
||||||
|
|
||||||
public Contribution(Uri contentUri, String filename, Uri localUri, String imageUrl, Date dateCreated,
|
public Contribution(Uri contentUri, String filename, Uri localUri, String imageUrl, Date dateCreated,
|
||||||
int state, long dataLength, Date dateUploaded, long transferred,
|
int state, long dataLength, Date dateUploaded, long transferred,
|
||||||
|
|
@ -269,6 +282,7 @@ public class Contribution extends Media {
|
||||||
this.contentProviderUri = contentProviderUri;
|
this.contentProviderUri = contentProviderUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -290,6 +304,7 @@ public class Contribution extends Media {
|
||||||
dest.writeString(this.p18Value);
|
dest.writeString(this.p18Value);
|
||||||
dest.writeParcelable(this.contentProviderUri, flags);
|
dest.writeParcelable(this.contentProviderUri, flags);
|
||||||
dest.writeString(this.dateCreatedSource);
|
dest.writeString(this.dateCreatedSource);
|
||||||
|
dest.writeInt(this.hasInvalidLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Contribution(Parcel in) {
|
protected Contribution(Parcel in) {
|
||||||
|
|
@ -307,6 +322,7 @@ public class Contribution extends Media {
|
||||||
this.p18Value = in.readString();
|
this.p18Value = in.readString();
|
||||||
this.contentProviderUri = in.readParcelable(Uri.class.getClassLoader());
|
this.contentProviderUri = in.readParcelable(Uri.class.getClassLoader());
|
||||||
this.dateCreatedSource = in.readString();
|
this.dateCreatedSource = in.readString();
|
||||||
|
this.hasInvalidLocation = in.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Creator<Contribution> CREATOR = new Creator<Contribution>() {
|
public static final Creator<Contribution> CREATOR = new Creator<Contribution>() {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import androidx.room.TypeConverters;
|
||||||
import fr.free.nrw.commons.contributions.Contribution;
|
import fr.free.nrw.commons.contributions.Contribution;
|
||||||
import fr.free.nrw.commons.contributions.ContributionDao;
|
import fr.free.nrw.commons.contributions.ContributionDao;
|
||||||
|
|
||||||
@Database(entities = {Contribution.class}, version = 1, exportSchema = false)
|
@Database(entities = {Contribution.class}, version = 2, exportSchema = false)
|
||||||
@TypeConverters({Converters.class})
|
@TypeConverters({Converters.class})
|
||||||
abstract public class AppDatabase extends RoomDatabase {
|
abstract public class AppDatabase extends RoomDatabase {
|
||||||
public abstract ContributionDao getContributionDao();
|
public abstract ContributionDao getContributionDao();
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import android.content.Context;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import androidx.collection.LruCache;
|
import androidx.collection.LruCache;
|
||||||
import androidx.room.Room;
|
import androidx.room.Room;
|
||||||
|
import androidx.room.migration.Migration;
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||||
import com.github.varunpant.quadtree.QuadTree;
|
import com.github.varunpant.quadtree.QuadTree;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
|
|
@ -52,6 +54,14 @@ public class CommonsApplicationModule {
|
||||||
public static final String MAIN_THREAD="main_thread";
|
public static final String MAIN_THREAD="main_thread";
|
||||||
private AppDatabase appDatabase;
|
private AppDatabase appDatabase;
|
||||||
|
|
||||||
|
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
|
||||||
|
@Override
|
||||||
|
public void migrate(SupportSQLiteDatabase database) {
|
||||||
|
database.execSQL("ALTER TABLE contribution "
|
||||||
|
+ " ADD COLUMN hasInvalidLocation INTEGER");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public CommonsApplicationModule(Context applicationContext) {
|
public CommonsApplicationModule(Context applicationContext) {
|
||||||
this.applicationContext = applicationContext;
|
this.applicationContext = applicationContext;
|
||||||
}
|
}
|
||||||
|
|
@ -231,7 +241,9 @@ public class CommonsApplicationModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public AppDatabase provideAppDataBase() {
|
public AppDatabase provideAppDataBase() {
|
||||||
appDatabase=Room.databaseBuilder(applicationContext, AppDatabase.class, "commons_room.db").build();
|
appDatabase=Room.databaseBuilder(applicationContext, AppDatabase.class, "commons_room.db")
|
||||||
|
.addMigrations(MIGRATION_1_2)
|
||||||
|
.build();
|
||||||
return appDatabase;
|
return appDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ public class UploadModel {
|
||||||
contribution.setSource(item.source);
|
contribution.setSource(item.source);
|
||||||
contribution.setContentProviderUri(item.mediaUri);
|
contribution.setContentProviderUri(item.mediaUri);
|
||||||
contribution.setDateUploaded(new Date());
|
contribution.setDateUploaded(new Date());
|
||||||
|
contribution.setHasInvalidLocation(item.hasInvalidLocation);
|
||||||
|
|
||||||
Timber.d("Created timestamp while building contribution is %s, %s",
|
Timber.d("Created timestamp while building contribution is %s, %s",
|
||||||
item.getCreatedTimestamp(),
|
item.getCreatedTimestamp(),
|
||||||
|
|
@ -221,6 +222,7 @@ public class UploadModel {
|
||||||
private final String mimeType;
|
private final String mimeType;
|
||||||
private final String source;
|
private final String source;
|
||||||
private ImageCoordinates gpsCoords;
|
private ImageCoordinates gpsCoords;
|
||||||
|
private boolean hasInvalidLocation;
|
||||||
|
|
||||||
public void setGpsCoords(ImageCoordinates gpsCoords) {
|
public void setGpsCoords(ImageCoordinates gpsCoords) {
|
||||||
this.gpsCoords = gpsCoords;
|
this.gpsCoords = gpsCoords;
|
||||||
|
|
@ -326,6 +328,10 @@ public class UploadModel {
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return mediaUri.hashCode();
|
return mediaUri.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHasInvalidLocation(boolean hasInvalidLocation) {
|
||||||
|
this.hasInvalidLocation=hasInvalidLocation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,15 @@ public class UploadService extends HandlerService<Contribution> {
|
||||||
Timber.d("Contribution upload success. Initiating Wikidata edit for"
|
Timber.d("Contribution upload success. Initiating Wikidata edit for"
|
||||||
+ " entity id %s if necessary (if P18 is null). P18 value is %s",
|
+ " entity id %s if necessary (if P18 is null). P18 value is %s",
|
||||||
contribution.getWikiDataEntityId(), contribution.getP18Value());
|
contribution.getWikiDataEntityId(), contribution.getP18Value());
|
||||||
wikidataEditService.createClaimWithLogging(contribution.getWikiDataEntityId(), contribution.getWikiItemName(), canonicalFilename, contribution.getP18Value());
|
if (!contribution.isHasInvalidLocation()) {
|
||||||
|
wikidataEditService
|
||||||
|
.createClaimWithLogging(contribution.getWikiDataEntityId(),
|
||||||
|
contribution.getWikiItemName(), canonicalFilename,
|
||||||
|
contribution.getP18Value());
|
||||||
|
} else {
|
||||||
|
Timber
|
||||||
|
.d("Image location and nearby place location mismatched, so Wikidata item won't be edited");
|
||||||
|
}
|
||||||
contribution.setFilename(canonicalFilename);
|
contribution.setFilename(canonicalFilename);
|
||||||
contribution.setImageUrl(uploadResult.getImageinfo().getOriginalUrl());
|
contribution.setImageUrl(uploadResult.getImageinfo().getOriginalUrl());
|
||||||
contribution.setState(Contribution.STATE_COMPLETED);
|
contribution.setState(Contribution.STATE_COMPLETED);
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
|
||||||
.observeOn(mainThreadScheduler)
|
.observeOn(mainThreadScheduler)
|
||||||
.subscribe(imageResult -> {
|
.subscribe(imageResult -> {
|
||||||
view.showProgress(false);
|
view.showProgress(false);
|
||||||
handleImageResult(imageResult);
|
handleImageResult(imageResult, uploadItem);
|
||||||
},
|
},
|
||||||
throwable -> {
|
throwable -> {
|
||||||
view.showProgress(false);
|
view.showProgress(false);
|
||||||
|
|
@ -165,13 +165,16 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
|
||||||
/**
|
/**
|
||||||
* handles image quality verifications
|
* handles image quality verifications
|
||||||
*
|
*
|
||||||
* @param imageResult
|
* @param imageResult
|
||||||
*/
|
* @param uploadItem
|
||||||
public void handleImageResult(Integer imageResult) {
|
*/
|
||||||
|
public void handleImageResult(Integer imageResult,
|
||||||
|
UploadItem uploadItem) {
|
||||||
if (imageResult == IMAGE_KEEP || imageResult == IMAGE_OK) {
|
if (imageResult == IMAGE_KEEP || imageResult == IMAGE_OK) {
|
||||||
view.onImageValidationSuccess();
|
view.onImageValidationSuccess();
|
||||||
|
uploadItem.setHasInvalidLocation(false);
|
||||||
} else {
|
} else {
|
||||||
handleBadImage(imageResult);
|
handleBadImage(imageResult, uploadItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,12 +182,14 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
|
||||||
* Handle images, say empty title, duplicate file name, bad picture(in all other cases)
|
* Handle images, say empty title, duplicate file name, bad picture(in all other cases)
|
||||||
*
|
*
|
||||||
* @param errorCode
|
* @param errorCode
|
||||||
|
* @param uploadItem
|
||||||
*/
|
*/
|
||||||
public void handleBadImage(Integer errorCode) {
|
public void handleBadImage(Integer errorCode,
|
||||||
|
UploadItem uploadItem) {
|
||||||
Timber.d("Handle bad picture with error code %d", errorCode);
|
Timber.d("Handle bad picture with error code %d", errorCode);
|
||||||
if (errorCode
|
if (errorCode
|
||||||
>= 8) { // If location of image and nearby does not match, then set shared preferences to disable wikidata edits
|
>= 8) { // If location of image and nearby does not match, then set shared preferences to disable wikidata edits
|
||||||
repository.saveValue("Picture_Has_Correct_Location", false);
|
uploadItem.setHasInvalidLocation(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (errorCode) {
|
switch (errorCode) {
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,6 @@ public class WikidataEditService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(directKvStore.getBoolean("Picture_Has_Correct_Location", true))) {
|
|
||||||
Timber.d("Image location and nearby place location mismatched, so Wikidata item won't be edited");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p18Value != null && !p18Value.trim().isEmpty()) {
|
if (p18Value != null && !p18Value.trim().isEmpty()) {
|
||||||
Timber.d("Skipping creation of claim as p18Value is not empty, we won't override existing image");
|
Timber.d("Skipping creation of claim as p18Value is not empty, we won't override existing image");
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -109,20 +109,20 @@ class UploadMediaPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun handleImageResult() {
|
fun handleImageResult() {
|
||||||
//Positive case test
|
//Positive case test
|
||||||
uploadMediaPresenter.handleImageResult(IMAGE_KEEP)
|
uploadMediaPresenter.handleImageResult(IMAGE_KEEP, uploadItem)
|
||||||
verify(view).onImageValidationSuccess()
|
verify(view).onImageValidationSuccess()
|
||||||
|
|
||||||
//Duplicate file name
|
//Duplicate file name
|
||||||
uploadMediaPresenter.handleImageResult(FILE_NAME_EXISTS)
|
uploadMediaPresenter.handleImageResult(FILE_NAME_EXISTS, uploadItem)
|
||||||
verify(view).showDuplicatePicturePopup()
|
verify(view).showDuplicatePicturePopup()
|
||||||
|
|
||||||
//Empty Title test
|
//Empty Title test
|
||||||
uploadMediaPresenter.handleImageResult(EMPTY_TITLE)
|
uploadMediaPresenter.handleImageResult(EMPTY_TITLE, uploadItem)
|
||||||
verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
|
verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
|
||||||
|
|
||||||
//Bad Picture test
|
//Bad Picture test
|
||||||
//Empty Title test
|
//Empty Title test
|
||||||
uploadMediaPresenter.handleImageResult(-7)
|
uploadMediaPresenter.handleImageResult(-7, uploadItem)
|
||||||
verify(view).showBadImagePopup(ArgumentMatchers.anyInt())
|
verify(view).showBadImagePopup(ArgumentMatchers.anyInt())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -158,8 +158,8 @@ class UploadMediaPresenterTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun handleBadImageBaseTestInvalidLocation() {
|
fun handleBadImageBaseTestInvalidLocation() {
|
||||||
uploadMediaPresenter.handleBadImage(8)
|
uploadMediaPresenter.handleBadImage(8, uploadItem)
|
||||||
verify(repository).saveValue(ArgumentMatchers.anyString(), eq(false))
|
verify(uploadItem).setHasInvalidLocation(true)
|
||||||
verify(view).showBadImagePopup(8)
|
verify(view).showBadImagePopup(8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,7 +168,7 @@ class UploadMediaPresenterTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun handleBadImageBaseTestEmptyTitle() {
|
fun handleBadImageBaseTestEmptyTitle() {
|
||||||
uploadMediaPresenter.handleBadImage(-3)
|
uploadMediaPresenter.handleBadImage(-3, uploadItem)
|
||||||
verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
|
verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,7 +177,7 @@ class UploadMediaPresenterTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun handleBadImageBaseTestFileNameExists() {
|
fun handleBadImageBaseTestFileNameExists() {
|
||||||
uploadMediaPresenter.handleBadImage(-4)
|
uploadMediaPresenter.handleBadImage(-4, uploadItem)
|
||||||
verify(view).showDuplicatePicturePopup()
|
verify(view).showDuplicatePicturePopup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,14 +50,6 @@ class WikidataEditServiceTest {
|
||||||
verifyZeroInteractions(wikidataClient!!)
|
verifyZeroInteractions(wikidataClient!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun noClaimsWhenLocationIsNotCorrect() {
|
|
||||||
`when`(directKvStore!!.getBoolean("Picture_Has_Correct_Location", true))
|
|
||||||
.thenReturn(false)
|
|
||||||
wikidataEditService!!.createClaimWithLogging("Q1", "","Test.jpg","")
|
|
||||||
verifyZeroInteractions(wikidataClient!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun createClaimWithLogging() {
|
fun createClaimWithLogging() {
|
||||||
`when`(directKvStore!!.getBoolean("Picture_Has_Correct_Location", true))
|
`when`(directKvStore!!.getBoolean("Picture_Has_Correct_Location", true))
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ buildscript {
|
||||||
maven { url "https://plugins.gradle.org/m2/" }
|
maven { url "https://plugins.gradle.org/m2/" }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.6.1'
|
classpath 'com.android.tools.build:gradle:3.6.3'
|
||||||
classpath "com.hiya:jacoco-android:0.2"
|
classpath "com.hiya:jacoco-android:0.2"
|
||||||
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'
|
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue