#3847 Convert Media and Contribution to Kotlin Data Classes - convert to data classes - compose a contribution with a media (#3848)

Co-authored-by: Vivek Maskara <maskaravivek@gmail.com>
This commit is contained in:
Seán Mac Gillicuddy 2020-06-30 20:41:56 +01:00 committed by GitHub
parent 3361155fad
commit cc2f14dab8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 334 additions and 741 deletions

View file

@ -16,6 +16,10 @@
<option name="REPORT_PARAMETERS" value="true" /> <option name="REPORT_PARAMETERS" value="true" />
</inspection_tool> </inspection_tool>
<inspection_tool class="LongLine" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="LongLine" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="MissingOverrideAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="ignoreObjectMethods" value="true" />
<option name="ignoreAnonymousClassMethods" value="false" />
</inspection_tool>
<inspection_tool class="NonFinalUtilityClass" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="NonFinalUtilityClass" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="OverlyStrongTypeCast" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="OverlyStrongTypeCast" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoreInMatchingInstanceof" value="false" /> <option name="ignoreInMatchingInstanceof" value="false" />

View file

@ -1,426 +0,0 @@
package fr.free.nrw.commons;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import fr.free.nrw.commons.location.LatLng;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import org.jetbrains.annotations.NotNull;
import org.wikipedia.page.PageTitle;
@Entity
public class Media implements Parcelable {
private String thumbUrl;
private String imageUrl;
private String filename;
private String fallbackDescription; // monolingual description on input...
@Nullable private Date dateUploaded;
private String license;
private String licenseUrl;
private String creator;
/**
* Wikibase Identifier associated with media files
*/
@PrimaryKey
@NonNull
private String pageId;
private List<String> categories; // as loaded at runtime?
@Nullable private LatLng coordinates;
@NotNull
private Map<String, String> captions = Collections.emptyMap();
@NotNull
private Map<String, String> descriptions = Collections.emptyMap();
@NotNull
private List<String> depictionIds = Collections.emptyList();
/**
* Provides local constructor
*/
public Media() {
pageId = UUID.randomUUID().toString();
}
/**
* Constructor with all parameters
*/
public Media(final String thumbUrl,
final String imageUrl,
final String filename,
final String fallbackDescription,
@Nullable final Date dateUploaded,
final String license,
final String licenseUrl,
final String creator,
@NonNull final String pageId,
final List<String> categories,
@Nullable final LatLng coordinates,
@NotNull final Map<String, String> captions,
@NotNull final Map<String, String> descriptions,
@NotNull final List<String> depictionIds) {
this.thumbUrl = thumbUrl;
this.imageUrl = imageUrl;
this.filename = filename;
this.fallbackDescription = fallbackDescription;
this.dateUploaded = dateUploaded;
this.license = license;
this.licenseUrl = licenseUrl;
this.creator = creator;
this.pageId = pageId;
this.categories = categories;
this.coordinates = coordinates;
this.captions = captions;
this.descriptions = descriptions;
this.depictionIds = depictionIds;
}
public Media(Media media) {
this(media.getThumbUrl(), media.getImageUrl(), media.getFilename(),
media.getFallbackDescription(), media.getDateUploaded(), media.getLicense(),
media.getLicenseUrl(), media.getCreator(), media.getPageId(), media.getCategories(),
media.getCoordinates(), media.getCaptions(), media.getDescriptions(),
media.getDepictionIds());
}
public Media(final String filename,
Map<String, String> captions, final String fallbackDescription,
final String creator, final List<String> categories) {
this();
thumbUrl = null;
this.imageUrl = null;
this.filename = filename;
this.fallbackDescription = fallbackDescription;
this.dateUploaded = new Date();
this.creator = creator;
this.categories = categories;
this.captions=captions;
}
protected Media(final Parcel in) {
this(in.readString(), in.readString(), in.readString(),
in.readString(), readDateUploaded(in), in.readString(),
in.readString(), in.readString(), in.readString(), readList(in),
in.readParcelable(LatLng.class.getClassLoader()),
((Map<String, String>) in.readSerializable()),
((Map<String, String>) in.readSerializable()),
readList(in));
}
private static List<String> readList(Parcel in) {
final List<String> list = new ArrayList<>();
in.readStringList(list);
return list;
}
private static Date readDateUploaded(Parcel in) {
final long tmpDateUploaded = in.readLong();
return tmpDateUploaded == -1 ? null : new Date(tmpDateUploaded);
}
public static final Creator<Media> CREATOR = new Creator<Media>() {
@Override
public Media createFromParcel(final Parcel source) {
return new Media(source);
}
@Override
public Media[] newArray(final int size) {
return new Media[size];
}
};
@Nullable
public String getThumbUrl() {
return thumbUrl;
}
/**
* Gets media display title
* @return Media title
*/
@NonNull public String getDisplayTitle() {
return filename != null ? getPageTitle().getDisplayTextWithoutNamespace().replaceFirst("[.][^.]+$", "") : "";
}
/**
* Gets file page title
* @return New media page title
*/
@NonNull public PageTitle getPageTitle() {
return Utils.getPageTitle(getFilename());
}
/**
* Gets image URL
* can be null.
* @return Image URL
*/
@Nullable
public String getImageUrl() {
return imageUrl;
}
/**
* Gets the name of the file.
* @return file name as a string
*/
public String getFilename() {
return filename;
}
/**
* @return pageId for the current media object*/
@NonNull
public String getPageId() {
return pageId;
}
/**
*sets pageId for the current media object
*/
public void setPageId(final String pageId) {
this.pageId = pageId;
}
/**
* Gets the file description.
* @return file description as a string
*/
public String getFallbackDescription() {
return fallbackDescription;
}
/**
* Sets the name of the file.
* @param filename the new name of the file
*/
public void setFilename(final String filename) {
this.filename = filename;
}
/**
* Sets the file description.
* @param fallbackDescription the new description of the file
*/
public void setFallbackDescription(final String fallbackDescription) {
this.fallbackDescription = fallbackDescription;
}
/**
* Gets the upload date of the file.
* Can be null.
* @return upload date as a Date
*/
public @Nullable
Date getDateUploaded() {
return dateUploaded;
}
/**
* Gets the name of the creator of the file.
* @return creator name as a String
*/
public String getCreator() {
return creator;
}
/**
* Gets the license name of the file.
* @return license as a String
*/
public String getLicense() {
return license;
}
public String getLicenseUrl() {
return licenseUrl;
}
/**
* Sets the creator name of the file.
* @param creator creator name as a string
*/
public void setCreator(final String creator) {
this.creator = creator;
}
/**
* Gets the coordinates of where the file was created.
* @return file coordinates as a LatLng
*/
public @Nullable
LatLng getCoordinates() {
return coordinates;
}
public void setThumbUrl(final String thumbUrl) {
this.thumbUrl = thumbUrl;
}
/**
* Gets the categories the file falls under.
* @return file categories as an ArrayList of Strings
*/
public List<String> getCategories() {
return categories;
}
/**
* Sets the coordinates of where the file was created.
* @param coordinates file coordinates as a LatLng
*/
public void setCoordinates(@Nullable final LatLng coordinates) {
this.coordinates = coordinates;
}
/**
* Returns wikicode to use the media file on a MediaWiki site
* @return
*/
public String getWikiCode() {
return String.format("[[%s|thumb|%s]]", filename, getMostRelevantCaption());
}
public String getMostRelevantCaption() {
final String languageAppropriateCaption = captions.get(Locale.getDefault().getLanguage());
if (languageAppropriateCaption != null) {
return languageAppropriateCaption;
}
for (String firstCaption : captions.values()) {
return firstCaption;
}
return getDisplayTitle();
}
/**
* Sets the categories the file falls under.
* </p>
* Does not append: i.e. will clear the current categories
* and then add the specified ones.
* @param categories file categories as a list of Strings
*/
public void setCategories(final List<String> categories) {
this.categories = categories;
}
/**
* Sets the license name of the file.
*
* @param license license name as a String
*/
public void setLicense(final String license) {
this.license = license;
}
public void setImageUrl(final String imageUrl) {
this.imageUrl = imageUrl;
}
public void setDateUploaded(@Nullable final Date dateUploaded) {
this.dateUploaded = dateUploaded;
}
public void setLicenseUrl(final String licenseUrl) {
this.licenseUrl = licenseUrl;
}
@Override
public int describeContents() {
return 0;
}
/**
* Creates a way to transfer information between two or more
* activities.
* @param dest Instance of Parcel
* @param flags Parcel flag
*/
@Override
public void writeToParcel(final Parcel dest, final int flags) {
dest.writeString(thumbUrl);
dest.writeString(imageUrl);
dest.writeString(filename);
dest.writeString(fallbackDescription);
dest.writeLong(dateUploaded != null ? dateUploaded.getTime() : -1);
dest.writeString(license);
dest.writeString(licenseUrl);
dest.writeString(creator);
dest.writeString(pageId);
dest.writeStringList(categories);
dest.writeParcelable(coordinates, flags);
dest.writeSerializable((Serializable) captions);
dest.writeSerializable((Serializable) descriptions);
dest.writeList(depictionIds);
}
public Map<String, String> getCaptions() {
return captions;
}
public void setCaptions(Map<String, String> captions) {
this.captions = captions;
}
public Map<String, String> getDescriptions() {
return descriptions;
}
public void setDescriptions(Map<String, String> descriptions) {
this.descriptions = descriptions;
}
public List<String> getDepictionIds() {
return depictionIds;
}
public void setDepictionIds(final List<String> depictionIds) {
this.depictionIds = depictionIds;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final Media media = (Media) o;
return Objects.equals(thumbUrl, media.thumbUrl) &&
Objects.equals(imageUrl, media.imageUrl) &&
Objects.equals(filename, media.filename) &&
Objects.equals(fallbackDescription, media.fallbackDescription) &&
Objects.equals(dateUploaded, media.dateUploaded) &&
Objects.equals(license, media.license) &&
Objects.equals(licenseUrl, media.licenseUrl) &&
Objects.equals(creator, media.creator) &&
pageId.equals(media.pageId) &&
Objects.equals(categories, media.categories) &&
Objects.equals(coordinates, media.coordinates) &&
captions.equals(media.captions) &&
descriptions.equals(media.descriptions) &&
depictionIds.equals(media.depictionIds);
}
@Override
public int hashCode() {
return Objects
.hash(thumbUrl, imageUrl, filename, fallbackDescription, dateUploaded, license,
licenseUrl,
creator, pageId, categories, coordinates, captions, descriptions, depictionIds);
}
}

View file

@ -0,0 +1,124 @@
package fr.free.nrw.commons
import android.os.Parcelable
import fr.free.nrw.commons.location.LatLng
import kotlinx.android.parcel.Parcelize
import org.wikipedia.page.PageTitle
import java.util.*
@Parcelize
class Media constructor(
/**
* @return pageId for the current media object
* Wikibase Identifier associated with media files
*/
val pageId: String = UUID.randomUUID().toString(),
val thumbUrl: String? = null,
/**
* Gets image URL
* @return Image URL
*/
val imageUrl: String? = null,
/**
* Gets the name of the file.
* @return file name as a string
*/
val filename: String? = null,
/**
* Gets the file description.
* @return file description as a string
*/
// monolingual description on input...
/**
* Sets the file description.
* @param fallbackDescription the new description of the file
*/
var fallbackDescription: String? = null,
/**
* Gets the upload date of the file.
* Can be null.
* @return upload date as a Date
*/
val dateUploaded: Date? = null,
/**
* Gets the license name of the file.
* @return license as a String
*/
/**
* Sets the license name of the file.
*
* @param license license name as a String
*/
var license: String? = null,
val licenseUrl: String? = null,
/**
* Gets the name of the creator of the file.
* @return creator name as a String
*/
/**
* Sets the creator name of the file.
* @param creator creator name as a string
*/
var creator: String? = null,
/**
* Gets the categories the file falls under.
* @return file categories as an ArrayList of Strings
*/
val categories: List<String>? = null,
/**
* Gets the coordinates of where the file was created.
* @return file coordinates as a LatLng
*/
val coordinates: LatLng? = null,
val captions: Map<String, String> = emptyMap(),
val descriptions: Map<String, String> = emptyMap(),
val depictionIds: List<String> = emptyList()
) : Parcelable {
constructor(
captions: Map<String, String>,
categories: List<String>?,
filename: String?,
fallbackDescription: String?,
creator: String?
) : this(
filename = filename,
fallbackDescription = fallbackDescription,
dateUploaded = Date(),
creator = creator,
categories = categories,
captions = captions
)
/**
* Gets media display title
* @return Media title
*/
val displayTitle: String
get() =
if (filename != null)
pageTitle.displayTextWithoutNamespace.replaceFirst("[.][^.]+$".toRegex(), "")
else
""
/**
* Gets file page title
* @return New media page title
*/
val pageTitle: PageTitle get() = Utils.getPageTitle(filename!!)
/**
* Returns wikicode to use the media file on a MediaWiki site
* @return
*/
val wikiCode: String
get() = String.format("[[%s|thumb|%s]]", filename, mostRelevantCaption)
val mostRelevantCaption: String
get() = captions[Locale.getDefault().language]
?: captions.values.firstOrNull()
?: displayTitle
}

View file

@ -32,7 +32,7 @@ class MediaDataExtractor @Inject constructor(private val mediaClient: MediaClien
mediaClient.checkPageExistsUsingTitle("Commons:Deletion_requests/" + media.filename) mediaClient.checkPageExistsUsingTitle("Commons:Deletion_requests/" + media.filename)
fun fetchDiscussion(media: Media) = fun fetchDiscussion(media: Media) =
mediaClient.getPageHtml(media.filename.replace("File", "File talk")) mediaClient.getPageHtml(media.filename!!.replace("File", "File talk"))
.map { HtmlCompat.fromHtml(it, HtmlCompat.FROM_HTML_MODE_LEGACY).toString() } .map { HtmlCompat.fromHtml(it, HtmlCompat.FROM_HTML_MODE_LEGACY).toString() }
.onErrorReturn { .onErrorReturn {
Timber.d("Error occurred while fetching discussion") Timber.d("Error occurred while fetching discussion")

View file

@ -144,4 +144,9 @@ public class BookmarksActivity extends NavigationBaseActivity
public void onMediaClicked(int position) { public void onMediaClicked(int position) {
//TODO use with pagination //TODO use with pagination
} }
@Override
public Integer getContributionStateAt(int position) {
return null;
}
} }

View file

@ -156,6 +156,11 @@ public class CategoryDetailsActivity extends NavigationBaseActivity
return categoriesMediaFragment.getTotalMediaCount(); return categoriesMediaFragment.getTotalMediaCount();
} }
@Override
public Integer getContributionStateAt(int position) {
return null;
}
/** /**
* This method inflates the menu in the toolbar * This method inflates the menu in the toolbar
*/ */

View file

@ -160,6 +160,11 @@ public class CategoryImagesActivity
return categoriesMediaFragment.getTotalMediaCount(); return categoriesMediaFragment.getTotalMediaCount();
} }
@Override
public Integer getContributionStateAt(int position) {
return null;
}
/** /**
* This method inflates the menu in the toolbar * This method inflates the menu in the toolbar
*/ */

View file

@ -1,220 +0,0 @@
package fr.free.nrw.commons.contributions;
import android.net.Uri;
import android.os.Parcel;
import androidx.annotation.Nullable;
import androidx.room.Entity;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.upload.UploadItem;
import fr.free.nrw.commons.upload.UploadMediaDetail;
import fr.free.nrw.commons.upload.WikidataPlace;
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@Entity(tableName = "contribution")
public class Contribution extends Media {
// No need to be bitwise - they're mutually exclusive
public static final int STATE_COMPLETED = -1;
public static final int STATE_FAILED = 1;
public static final int STATE_QUEUED = 2;
public static final int STATE_IN_PROGRESS = 3;
private int state;
private long transferred;
private String decimalCoords;
private String dateCreatedSource;
private WikidataPlace wikidataPlace;
/**
* Each depiction loaded in depictions activity is associated with a wikidata entity id, this Id
* is in turn used to upload depictions to wikibase
*/
private List<DepictedItem> depictedItems = new ArrayList<>();
private String mimeType;
@Nullable
private Uri localUri;
private long dataLength;
private Date dateCreated;
public Contribution() {
}
public Contribution(final UploadItem item, final SessionManager sessionManager,
final List<DepictedItem> depictedItems, final List<String> categories) {
super(
item.getFileName(),
UploadMediaDetail.formatCaptions(item.getUploadMediaDetails()),
UploadMediaDetail.formatDescriptions(item.getUploadMediaDetails()),
sessionManager.getAuthorName(),
categories);
localUri = item.getMediaUri();
decimalCoords = item.getGpsCoords().getDecimalCoords();
dateCreatedSource = "";
this.depictedItems = depictedItems;
wikidataPlace = WikidataPlace.from(item.getPlace());
}
public void setDateCreatedSource(final String dateCreatedSource) {
this.dateCreatedSource = dateCreatedSource;
}
public String getDateCreatedSource() {
return dateCreatedSource;
}
public long getTransferred() {
return transferred;
}
public void setTransferred(final long transferred) {
this.transferred = transferred;
}
public int getState() {
return state;
}
public void setState(final int state) {
this.state = state;
}
/**
* @return array list of entityids for the depictions
*/
public List<DepictedItem> getDepictedItems() {
return depictedItems;
}
public void setWikidataPlace(final WikidataPlace wikidataPlace) {
this.wikidataPlace = wikidataPlace;
}
public WikidataPlace getWikidataPlace() {
return wikidataPlace;
}
public String getDecimalCoords() {
return decimalCoords;
}
public void setDecimalCoords(final String decimalCoords) {
this.decimalCoords = decimalCoords;
}
public void setDepictedItems(final List<DepictedItem> depictedItems) {
this.depictedItems = depictedItems;
}
public String getMimeType() {
return mimeType;
}
public void setMimeType(final String mimeType) {
this.mimeType = mimeType;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(final Parcel dest, final int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(state);
dest.writeLong(transferred);
dest.writeString(decimalCoords);
dest.writeString(dateCreatedSource);
}
/**
* Constructor that takes Media object and state as parameters and builds a new Contribution object
* @param media
* @param state
*/
public Contribution(Media media, int state) {
super(media);
this.state = state;
}
protected Contribution(final Parcel in) {
super(in);
state = in.readInt();
transferred = in.readLong();
decimalCoords = in.readString();
dateCreatedSource = in.readString();
}
public static final Creator<Contribution> CREATOR = new Creator<Contribution>() {
@Override
public Contribution createFromParcel(final Parcel source) {
return new Contribution(source);
}
@Override
public Contribution[] newArray(final int size) {
return new Contribution[size];
}
};
@Nullable
public Uri getLocalUri() {
return localUri;
}
public void setLocalUri(@Nullable Uri localUri) {
this.localUri = localUri;
}
public long getDataLength() {
return dataLength;
}
public void setDataLength(long dataLength) {
this.dataLength = dataLength;
}
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
final Contribution that = (Contribution) o;
return state == that.state &&
transferred == that.transferred &&
dataLength == that.dataLength &&
Objects.equals(decimalCoords, that.decimalCoords) &&
Objects.equals(dateCreatedSource, that.dateCreatedSource) &&
Objects.equals(wikidataPlace, that.wikidataPlace) &&
Objects.equals(depictedItems, that.depictedItems) &&
Objects.equals(mimeType, that.mimeType) &&
Objects.equals(localUri, that.localUri) &&
Objects.equals(dateCreated, that.dateCreated);
}
@Override
public int hashCode() {
return Objects
.hash(super.hashCode(), state, transferred, decimalCoords, dateCreatedSource,
wikidataPlace,
depictedItems, mimeType, localUri, dataLength, dateCreated);
}
}

View file

@ -0,0 +1,90 @@
package fr.free.nrw.commons.contributions
import android.net.Uri
import android.os.Parcelable
import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.PrimaryKey
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.upload.UploadItem
import fr.free.nrw.commons.upload.UploadMediaDetail
import fr.free.nrw.commons.upload.WikidataPlace
import fr.free.nrw.commons.upload.WikidataPlace.Companion.from
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
import kotlinx.android.parcel.Parcelize
import java.util.*
@Entity(tableName = "contribution")
@Parcelize
data class Contribution constructor(
@Embedded(prefix = "media_") val media: Media,
@PrimaryKey val pageId: String = media.pageId,
var state: Int = 0,
var transferred: Long = 0,
val decimalCoords: String? = null,
var dateCreatedSource: String? = null,
var wikidataPlace: WikidataPlace? = null,
/**
* @return array list of entityids for the depictions
*/
/**
* Each depiction loaded in depictions activity is associated with a wikidata entity id, this Id
* is in turn used to upload depictions to wikibase
*/
val depictedItems: List<DepictedItem> = ArrayList(),
var mimeType: String? = null,
val localUri: Uri? = null,
var dataLength: Long = 0,
var dateCreated: Date? = null
) : Parcelable {
fun completeWith(media: Media): Contribution {
return copy(pageId = media.pageId, media = media, state = STATE_COMPLETED)
}
constructor(
item: UploadItem,
sessionManager: SessionManager,
depictedItems: List<DepictedItem>,
categories: List<String>
) : this(
Media(
formatCaptions(item.uploadMediaDetails),
categories,
item.fileName,
formatDescriptions(item.uploadMediaDetails),
sessionManager.authorName
),
localUri = item.mediaUri,
decimalCoords = item.gpsCoords.decimalCoords,
dateCreatedSource = "",
depictedItems = depictedItems,
wikidataPlace = from(item.place)
)
companion object {
const val STATE_COMPLETED = -1
const val STATE_FAILED = 1
const val STATE_QUEUED = 2
const val STATE_IN_PROGRESS = 3
/**
* Formatting captions to the Wikibase format for sending labels
* @param uploadMediaDetails list of media Details
*/
fun formatCaptions(uploadMediaDetails: List<UploadMediaDetail>) =
uploadMediaDetails.associate { it.languageCode!! to it.captionText }
.filter { it.value.isNotBlank() }
/**
* Formats the list of descriptions into the format Commons requires for uploads.
*
* @param descriptions the list of descriptions, description is ignored if text is null.
* @return a string with the pattern of {{en|1=descriptionText}}
*/
fun formatDescriptions(descriptions: List<UploadMediaDetail>) =
descriptions.filter { it.descriptionText.isNotEmpty() }
.joinToString { "{{${it.languageCode}|1=${it.descriptionText}}}" }
}
}

View file

@ -1,7 +1,6 @@
package fr.free.nrw.commons.contributions package fr.free.nrw.commons.contributions
import androidx.paging.PagedList.BoundaryCallback import androidx.paging.PagedList.BoundaryCallback
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.di.CommonsApplicationModule import fr.free.nrw.commons.di.CommonsApplicationModule
import fr.free.nrw.commons.media.MediaClient import fr.free.nrw.commons.media.MediaClient
@ -53,9 +52,9 @@ class ContributionBoundaryCallback @Inject constructor(
fun fetchContributions() { fun fetchContributions() {
compositeDisposable.add( compositeDisposable.add(
mediaClient.getMediaListForUser(sessionManager.userName!!) mediaClient.getMediaListForUser(sessionManager.userName!!)
.map { mediaList: List<Media?> -> .map { mediaList ->
mediaList.map { mediaList.map {
Contribution(it, Contribution.STATE_COMPLETED) Contribution(media=it, state=Contribution.STATE_COMPLETED)
} }
} }
.subscribeOn(ioThreadScheduler) .subscribeOn(ioThreadScheduler)

View file

@ -15,7 +15,7 @@ import java.util.List;
@Dao @Dao
public abstract class ContributionDao { public abstract class ContributionDao {
@Query("SELECT * FROM contribution order by dateUploaded DESC") @Query("SELECT * FROM contribution order by media_dateUploaded DESC")
abstract DataSource.Factory<Integer, Contribution> fetchContributions(); abstract DataSource.Factory<Integer, Contribution> fetchContributions();
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
@ -50,7 +50,7 @@ public abstract class ContributionDao {
.fromAction(() -> deleteSynchronous(contribution)); .fromAction(() -> deleteSynchronous(contribution));
} }
@Query("SELECT * from contribution WHERE filename=:fileName") @Query("SELECT * from contribution WHERE media_filename=:fileName")
public abstract List<Contribution> getContributionWithTitle(String fileName); public abstract List<Contribution> getContributionWithTitle(String fileName);
@Query("SELECT * from contribution WHERE pageId=:pageId") @Query("SELECT * from contribution WHERE pageId=:pageId")

View file

@ -61,8 +61,8 @@ public class ContributionViewHolder extends RecyclerView.ViewHolder {
public void init(final int position, final Contribution contribution) { public void init(final int position, final Contribution contribution) {
this.contribution = contribution; this.contribution = contribution;
this.position = position; this.position = position;
titleView.setText(contribution.getMostRelevantCaption()); titleView.setText(contribution.getMedia().getMostRelevantCaption());
final String imageSource = chooseImageSource(contribution.getThumbUrl(), final String imageSource = chooseImageSource(contribution.getMedia().getThumbUrl(),
contribution.getLocalUri()); contribution.getLocalUri());
if (!TextUtils.isEmpty(imageSource)) { if (!TextUtils.isEmpty(imageSource)) {
final ImageRequest imageRequest = final ImageRequest imageRequest =

View file

@ -41,7 +41,6 @@ import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
import fr.free.nrw.commons.nearby.NearbyController; import fr.free.nrw.commons.nearby.NearbyController;
import fr.free.nrw.commons.nearby.NearbyNotificationCardView; import fr.free.nrw.commons.nearby.NearbyNotificationCardView;
import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.upload.UploadService; import fr.free.nrw.commons.upload.UploadService;
import fr.free.nrw.commons.utils.ConfigUtils; import fr.free.nrw.commons.utils.ConfigUtils;
import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.DialogUtil;
@ -490,5 +489,10 @@ public class ContributionsFragment
public int getTotalMediaCount() { public int getTotalMediaCount() {
return contributionsListFragment.getTotalMediaCount(); return contributionsListFragment.getTotalMediaCount();
} }
@Override
public Integer getContributionStateAt(int position) {
return contributionsListFragment.getContributionStateAt(position);
}
} }

View file

@ -278,7 +278,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
public Media getMediaAtPosition(final int i) { public Media getMediaAtPosition(final int i) {
return adapter.getContributionForPosition(i); return adapter.getContributionForPosition(i).getMedia();
} }
public int getTotalMediaCount() { public int getTotalMediaCount() {
@ -303,6 +303,10 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
Utils.handleWebUrl(getContext(), Uri.parse(url)); Utils.handleWebUrl(getContext(), Uri.parse(url));
} }
public Integer getContributionStateAt(int position) {
return adapter.getContributionForPosition(position).getState();
}
public interface Callback { public interface Callback {
void retryUpload(Contribution contribution); void retryUpload(Contribution contribution);

View file

@ -30,7 +30,7 @@ class WikipediaInstructionsDialogFragment : DialogFragment() {
) { ) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
contribution = arguments!!.getParcelable(ARG_CONTRIBUTION) contribution = arguments!!.getParcelable(ARG_CONTRIBUTION)
tv_wikicode.setText(contribution?.wikiCode) tv_wikicode.setText(contribution?.media?.wikiCode)
instructions_cancel.setOnClickListener { instructions_cancel.setOnClickListener {
dismiss() dismiss()
} }

View file

@ -10,7 +10,7 @@ import fr.free.nrw.commons.contributions.ContributionDao
* The database for accessing the respective DAOs * The database for accessing the respective DAOs
* *
*/ */
@Database(entities = [Contribution::class], version = 3, exportSchema = false) @Database(entities = [Contribution::class], version = 4, exportSchema = false)
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
abstract fun contributionDao(): ContributionDao abstract fun contributionDao(): ContributionDao

View file

@ -134,6 +134,11 @@ public class ExploreActivity
} }
} }
@Override
public Integer getContributionStateAt(int position) {
return null;
}
/** /**
* This method is called on success of API call for featured images or mobile uploads. * This method is called on success of API call for featured images or mobile uploads.
* The viewpager will notified that number of items have changed. * The viewpager will notified that number of items have changed.

View file

@ -176,6 +176,11 @@ public class SearchActivity extends NavigationBaseActivity
return searchMediaFragment.getTotalMediaCount(); return searchMediaFragment.getTotalMediaCount();
} }
@Override
public Integer getContributionStateAt(int position) {
return null;
}
/** /**
* This method is called on success of API call for image Search. * This method is called on success of API call for image Search.
* The viewpager will notified that number of items have changed. * The viewpager will notified that number of items have changed.

View file

@ -173,6 +173,11 @@ public class WikidataItemDetailsActivity extends NavigationBaseActivity implemen
return depictionImagesListFragment.getTotalMediaCount(); return depictionImagesListFragment.getTotalMediaCount();
} }
@Override
public Integer getContributionStateAt(int position) {
return null;
}
/** /**
* Consumers should be simply using this method to use this activity. * Consumers should be simply using this method to use this activity.
* *

View file

@ -17,14 +17,11 @@ import java.util.*
import javax.inject.Inject import javax.inject.Inject
class MediaConverter @Inject constructor() { class MediaConverter @Inject constructor() {
fun convert( fun convert(page: MwQueryPage, entity: Entities.Entity, imageInfo: ImageInfo): Media {
page: MwQueryPage,
entity: Entities.Entity,
imageInfo: ImageInfo
): Media {
val metadata = imageInfo.metadata val metadata = imageInfo.metadata
requireNotNull(metadata) { "No metadata" } requireNotNull(metadata) { "No metadata" }
return Media( return Media(
page.pageId().toString(),
imageInfo.thumbUrl.takeIf { it.isNotBlank() } ?: imageInfo.originalUrl, imageInfo.thumbUrl.takeIf { it.isNotBlank() } ?: imageInfo.originalUrl,
imageInfo.originalUrl, imageInfo.originalUrl,
page.title(), page.title(),
@ -33,14 +30,12 @@ class MediaConverter @Inject constructor() {
metadata.licenseShortName(), metadata.licenseShortName(),
metadata.prefixedLicenseUrl, metadata.prefixedLicenseUrl,
getArtist(metadata), getArtist(metadata),
page.pageId().toString(),
MediaDataExtractorUtil.extractCategoriesFromList(metadata.categories), MediaDataExtractorUtil.extractCategoriesFromList(metadata.categories),
metadata.latLng, metadata.latLng,
entity.labels().mapValues { it.value.value() }, entity.labels().mapValues { it.value.value() },
entity.descriptions().mapValues { it.value.value() }, entity.descriptions().mapValues { it.value.value() },
entity.depictionIds() entity.depictionIds()
) )
} }
/** /**

View file

@ -49,4 +49,6 @@ abstract class PageableMediaFragment : BasePagingFragment<Media>(), MediaDetailP
} }
override fun getTotalMediaCount(): Int = pagedListAdapter.itemCount override fun getTotalMediaCount(): Int = pagedListAdapter.itemCount
override fun getContributionStateAt(position: Int) = null
} }

View file

@ -188,7 +188,8 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
return; return;
} }
Media m = provider.getMediaAtPosition(pager.getCurrentItem()); final int position = pager.getCurrentItem();
Media m = provider.getMediaAtPosition(position);
if (m != null) { if (m != null) {
// Enable default set of actions, then re-enable different set of actions only if it is a failed contrib // Enable default set of actions, then re-enable different set of actions only if it is a failed contrib
menu.findItem(R.id.menu_browser_current_image).setEnabled(true).setVisible(true); menu.findItem(R.id.menu_browser_current_image).setEnabled(true).setVisible(true);
@ -204,10 +205,9 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
BookmarkPicturesContentProvider.uriForName(m.getFilename()) BookmarkPicturesContentProvider.uriForName(m.getFilename())
); );
updateBookmarkState(menu.findItem(R.id.menu_bookmark_current_image)); updateBookmarkState(menu.findItem(R.id.menu_bookmark_current_image));
final Integer contributionState = provider.getContributionStateAt(position);
if (m instanceof Contribution) { if (contributionState != null) {
Contribution c = (Contribution) m; switch (contributionState) {
switch (c.getState()) {
case Contribution.STATE_FAILED: case Contribution.STATE_FAILED:
case Contribution.STATE_IN_PROGRESS: case Contribution.STATE_IN_PROGRESS:
case Contribution.STATE_QUEUED: case Contribution.STATE_QUEUED:
@ -289,6 +289,8 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
Media getMediaAtPosition(int i); Media getMediaAtPosition(int i);
int getTotalMediaCount(); int getTotalMediaCount();
Integer getContributionStateAt(int position);
} }
//FragmentStatePagerAdapter allows user to swipe across collection of images (no. of images undetermined) //FragmentStatePagerAdapter allows user to swipe across collection of images (no. of images undetermined)

View file

@ -2,6 +2,7 @@ package fr.free.nrw.commons.upload;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.Contribution;
import fr.free.nrw.commons.filepicker.UploadableFile.DateTimeWithSource; import fr.free.nrw.commons.filepicker.UploadableFile.DateTimeWithSource;
import fr.free.nrw.commons.settings.Prefs.Licenses; import fr.free.nrw.commons.settings.Prefs.Licenses;
@ -30,13 +31,14 @@ class PageContentsCreator {
public String createFrom(Contribution contribution) { public String createFrom(Contribution contribution) {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
final Media media = contribution.getMedia();
buffer buffer
.append("== {{int:filedesc}} ==\n") .append("== {{int:filedesc}} ==\n")
.append("{{Information\n") .append("{{Information\n")
.append("|description=").append(contribution.getFallbackDescription()).append("\n") .append("|description=").append(media.getFallbackDescription()).append("\n")
.append("|source=").append("{{own}}\n") .append("|source=").append("{{own}}\n")
.append("|author=[[User:").append(contribution.getCreator()).append("|") .append("|author=[[User:").append(media.getCreator()).append("|")
.append(contribution.getCreator()).append("]]\n"); .append(media.getCreator()).append("]]\n");
String templatizedCreatedDate = getTemplatizedCreatedDate( String templatizedCreatedDate = getTemplatizedCreatedDate(
contribution.getDateCreated(), contribution.getDateCreatedSource()); contribution.getDateCreated(), contribution.getDateCreatedSource());
@ -53,10 +55,10 @@ class PageContentsCreator {
} }
buffer.append("== {{int:license-header}} ==\n") buffer.append("== {{int:license-header}} ==\n")
.append(licenseTemplateFor(contribution.getLicense())).append("\n\n") .append(licenseTemplateFor(media.getLicense())).append("\n\n")
.append("{{Uploaded from Mobile|platform=Android|version=") .append("{{Uploaded from Mobile|platform=Android|version=")
.append(ConfigUtils.getVersionNameWithSha(context)).append("}}\n"); .append(ConfigUtils.getVersionNameWithSha(context)).append("}}\n");
final List<String> categories = contribution.getCategories(); final List<String> categories = media.getCategories();
if (categories != null && categories.size() != 0) { if (categories != null && categories.size() != 0) {
for (int i = 0; i < categories.size(); i++) { for (int i = 0; i < categories.size(); i++) {
buffer.append("\n[[Category:").append(categories.get(i)).append("]]"); buffer.append("\n[[Category:").append(categories.get(i)).append("]]");

View file

@ -13,6 +13,7 @@ import android.net.Uri;
import android.os.IBinder; import android.os.IBinder;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.text.TextUtils; import android.text.TextUtils;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.Contribution;
@ -93,12 +94,13 @@ public class UploadController {
//Set creator, desc, and license //Set creator, desc, and license
// If author name is enabled and set, use it // If author name is enabled and set, use it
final Media media = contribution.getMedia();
if (store.getBoolean("useAuthorName", false)) { if (store.getBoolean("useAuthorName", false)) {
final String authorName = store.getString("authorName", ""); final String authorName = store.getString("authorName", "");
contribution.setCreator(authorName); media.setCreator(authorName);
} }
if (TextUtils.isEmpty(contribution.getCreator())) { if (TextUtils.isEmpty(media.getCreator())) {
final Account currentAccount = sessionManager.getCurrentAccount(); final Account currentAccount = sessionManager.getCurrentAccount();
if (currentAccount == null) { if (currentAccount == null) {
Timber.d("Current account is null"); Timber.d("Current account is null");
@ -106,15 +108,15 @@ public class UploadController {
sessionManager.forceLogin(context); sessionManager.forceLogin(context);
return; return;
} }
contribution.setCreator(sessionManager.getAuthorName()); media.setCreator(sessionManager.getAuthorName());
} }
if (contribution.getFallbackDescription() == null) { if (media.getFallbackDescription() == null) {
contribution.setFallbackDescription(""); media.setFallbackDescription("");
} }
final String license = store.getString(Prefs.DEFAULT_LICENSE, Prefs.Licenses.CC_BY_SA_3); final String license = store.getString(Prefs.DEFAULT_LICENSE, Prefs.Licenses.CC_BY_SA_3);
contribution.setLicense(license); media.setLicense(license);
uploadTask(contribution); uploadTask(contribution);
} }

View file

@ -41,24 +41,4 @@ data class UploadMediaDetail constructor(
*/ */
var isManuallyAdded: Boolean = false var isManuallyAdded: Boolean = false
companion object {
/**
* Formatting captions to the Wikibase format for sending labels
* @param uploadMediaDetails list of media Details
*/
@JvmStatic
fun formatCaptions(uploadMediaDetails: List<UploadMediaDetail>) =
uploadMediaDetails.associate { it.languageCode to it.captionText }.filter { it.value.isNotBlank() }
/**
* Formats the list of descriptions into the format Commons requires for uploads.
*
* @param descriptions the list of descriptions, description is ignored if text is null.
* @return a string with the pattern of {{en|1=descriptionText}}
*/
@JvmStatic
fun formatDescriptions(descriptions: List<UploadMediaDetail>) =
descriptions.filter { it.descriptionText.isNotEmpty() }
.joinToString { "{{${it.languageCode}|1=${it.descriptionText}}}" }
}
} }

View file

@ -13,6 +13,7 @@ import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import fr.free.nrw.commons.BuildConfig; import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.Contribution;
@ -216,25 +217,27 @@ public class UploadService extends CommonsDaggerService {
File localFile = new File(localUri.getPath()); File localFile = new File(localUri.getPath());
Timber.d("Before execution!"); Timber.d("Before execution!");
final Media media = contribution.getMedia();
final String displayTitle = media.getDisplayTitle();
curNotification.setContentTitle(getString(R.string.upload_progress_notification_title_start, curNotification.setContentTitle(getString(R.string.upload_progress_notification_title_start,
contribution.getDisplayTitle())) displayTitle))
.setContentText(getResources() .setContentText(getResources()
.getQuantityString(R.plurals.uploads_pending_notification_indicator, toUpload, .getQuantityString(R.plurals.uploads_pending_notification_indicator, toUpload,
toUpload)) toUpload))
.setTicker(getString(R.string.upload_progress_notification_title_in_progress, .setTicker(getString(R.string.upload_progress_notification_title_in_progress,
contribution.getDisplayTitle())) displayTitle))
.setOngoing(true); .setOngoing(true);
notificationManager notificationManager
.notify(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS, curNotification.build()); .notify(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS, curNotification.build());
String filename = contribution.getFilename(); String filename = media.getFilename();
NotificationUpdateProgressListener notificationUpdater = new NotificationUpdateProgressListener( NotificationUpdateProgressListener notificationUpdater = new NotificationUpdateProgressListener(
notificationTag, notificationTag,
getString(R.string.upload_progress_notification_title_in_progress, getString(R.string.upload_progress_notification_title_in_progress,
contribution.getDisplayTitle()), displayTitle),
getString(R.string.upload_progress_notification_title_finishing, getString(R.string.upload_progress_notification_title_finishing,
contribution.getDisplayTitle()), displayTitle),
contribution contribution
); );
@ -312,13 +315,7 @@ public class UploadService extends CommonsDaggerService {
private void saveCompletedContribution(Contribution contribution, UploadResult uploadResult) { private void saveCompletedContribution(Contribution contribution, UploadResult uploadResult) {
compositeDisposable.add(mediaClient.getMedia("File:" + uploadResult.getFilename()) compositeDisposable.add(mediaClient.getMedia("File:" + uploadResult.getFilename())
.map(media -> { .map(contribution::completeWith)
Contribution newContribution = new Contribution(media, Contribution.STATE_COMPLETED);
if (contribution.getWikidataPlace() != null) {
newContribution.setWikidataPlace(contribution.getWikidataPlace());
}
return newContribution;
})
.flatMapCompletable( .flatMapCompletable(
newContribution -> contributionDao.saveAndDelete(contribution, newContribution)) newContribution -> contributionDao.saveAndDelete(contribution, newContribution))
.subscribe()); .subscribe());
@ -327,10 +324,9 @@ public class UploadService extends CommonsDaggerService {
@SuppressLint("StringFormatInvalid") @SuppressLint("StringFormatInvalid")
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private void showFailedNotification(Contribution contribution) { private void showFailedNotification(Contribution contribution) {
curNotification.setTicker( final String displayTitle = contribution.getMedia().getDisplayTitle();
getString(R.string.upload_failed_notification_title, contribution.getDisplayTitle())) curNotification.setTicker(getString(R.string.upload_failed_notification_title, displayTitle))
.setContentTitle( .setContentTitle(getString(R.string.upload_failed_notification_title, displayTitle))
getString(R.string.upload_failed_notification_title, contribution.getDisplayTitle()))
.setContentText(getString(R.string.upload_failed_notification_subtitle)) .setContentText(getString(R.string.upload_failed_notification_subtitle))
.setProgress(0, 0, false) .setProgress(0, 0, false)
.setOngoing(false); .setOngoing(false);

View file

@ -5,7 +5,7 @@ import fr.free.nrw.commons.nearby.Place
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
internal data class WikidataPlace( data class WikidataPlace(
override val id: String, override val id: String,
override val name: String, override val name: String,
val imageValue: String?, val imageValue: String?,

View file

@ -1,9 +1,11 @@
package fr.free.nrw.commons.upload.structure.depictions package fr.free.nrw.commons.upload.structure.depictions
import android.os.Parcelable
import fr.free.nrw.commons.nearby.Place import fr.free.nrw.commons.nearby.Place
import fr.free.nrw.commons.upload.WikidataItem import fr.free.nrw.commons.upload.WikidataItem
import fr.free.nrw.commons.wikidata.WikidataProperties import fr.free.nrw.commons.wikidata.WikidataProperties
import fr.free.nrw.commons.wikidata.WikidataProperties.* import fr.free.nrw.commons.wikidata.WikidataProperties.*
import kotlinx.android.parcel.Parcelize
import org.wikipedia.wikidata.DataValue import org.wikipedia.wikidata.DataValue
import org.wikipedia.wikidata.Entities import org.wikipedia.wikidata.Entities
import org.wikipedia.wikidata.Statement_partial import org.wikipedia.wikidata.Statement_partial
@ -17,6 +19,7 @@ const val THUMB_IMAGE_SIZE = "70px"
/** /**
* Model class for Depicted Item in Upload and Explore * Model class for Depicted Item in Upload and Explore
*/ */
@Parcelize
data class DepictedItem constructor( data class DepictedItem constructor(
override val name: String, override val name: String,
val description: String?, val description: String?,
@ -25,7 +28,7 @@ data class DepictedItem constructor(
val commonsCategories: List<String>, val commonsCategories: List<String>,
var isSelected: Boolean, var isSelected: Boolean,
override val id: String override val id: String
) : WikidataItem { ) : WikidataItem, Parcelable {
constructor(entity: Entities.Entity) : this( constructor(entity: Entities.Entity) : this(
entity, entity,

View file

@ -214,7 +214,7 @@ public class WikidataEditService {
} }
private Observable<Boolean> captionEdits(Contribution contribution, Long fileEntityId) { private Observable<Boolean> captionEdits(Contribution contribution, Long fileEntityId) {
return Observable.fromIterable(contribution.getCaptions().entrySet()) return Observable.fromIterable(contribution.getMedia().getCaptions().entrySet())
.concatMap(entry -> addCaption(fileEntityId, entry.getKey(), entry.getValue())); .concatMap(entry -> addCaption(fileEntityId, entry.getKey(), entry.getValue()));
} }

View file

@ -44,10 +44,11 @@ fun media(
pageId: String = "pageId", pageId: String = "pageId",
categories: List<String>? = listOf("categories"), categories: List<String>? = listOf("categories"),
coordinates: LatLng? = LatLng(0.0, 0.0, 0.0f), coordinates: LatLng? = LatLng(0.0, 0.0, 0.0f),
captions: Map<String?, String?> = mapOf("en" to "caption"), captions: Map<String, String> = mapOf("en" to "caption"),
descriptions: Map<String?, String?> = mapOf("en" to "description"), descriptions: Map<String, String> = mapOf("en" to "description"),
depictionIds: List<String> = listOf("depictionId") depictionIds: List<String> = listOf("depictionId")
) = Media( ) = Media(
pageId,
thumbUrl, thumbUrl,
imageUrl, imageUrl,
filename, filename,
@ -56,7 +57,6 @@ fun media(
license, license,
licenseUrl, licenseUrl,
creator, creator,
pageId,
categories, categories,
coordinates, coordinates,
captions, captions,

View file

@ -4,12 +4,12 @@ import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.verifyZeroInteractions import com.nhaarman.mockitokotlin2.verifyZeroInteractions
import com.nhaarman.mockitokotlin2.whenever import com.nhaarman.mockitokotlin2.whenever
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.media.MediaClient import fr.free.nrw.commons.media.MediaClient
import io.reactivex.Scheduler import io.reactivex.Scheduler
import io.reactivex.Single import io.reactivex.Single
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import media
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -57,9 +57,8 @@ class ContributionBoundaryCallbackTest {
whenever(repository.save(anyList<Contribution>())) whenever(repository.save(anyList<Contribution>()))
.thenReturn(Single.just(listOf(1L, 2L))) .thenReturn(Single.just(listOf(1L, 2L)))
whenever(sessionManager.userName).thenReturn("Test") whenever(sessionManager.userName).thenReturn("Test")
whenever(mediaClient.getMediaListForUser(anyString())).thenReturn( whenever(mediaClient.getMediaListForUser(anyString()))
Single.just(listOf(mock(Media::class.java))) .thenReturn(Single.just(listOf(media())))
)
contributionBoundaryCallback.onZeroItemsLoaded() contributionBoundaryCallback.onZeroItemsLoaded()
verify(repository).save(anyList<Contribution>()); verify(repository).save(anyList<Contribution>());
verify(mediaClient).getMediaListForUser(anyString()); verify(mediaClient).getMediaListForUser(anyString());
@ -70,9 +69,8 @@ class ContributionBoundaryCallbackTest {
whenever(repository.save(anyList<Contribution>())) whenever(repository.save(anyList<Contribution>()))
.thenReturn(Single.just(listOf(1L, 2L))) .thenReturn(Single.just(listOf(1L, 2L)))
whenever(sessionManager.userName).thenReturn("Test") whenever(sessionManager.userName).thenReturn("Test")
whenever(mediaClient.getMediaListForUser(anyString())).thenReturn( whenever(mediaClient.getMediaListForUser(anyString()))
Single.just(listOf(mock(Media::class.java))) .thenReturn(Single.just(listOf(media())))
)
contributionBoundaryCallback.onItemAtEndLoaded(mock(Contribution::class.java)) contributionBoundaryCallback.onItemAtEndLoaded(mock(Contribution::class.java))
verify(repository).save(anyList()); verify(repository).save(anyList());
verify(mediaClient).getMediaListForUser(anyString()); verify(mediaClient).getMediaListForUser(anyString());
@ -83,9 +81,8 @@ class ContributionBoundaryCallbackTest {
whenever(repository.save(anyList<Contribution>())) whenever(repository.save(anyList<Contribution>()))
.thenReturn(Single.just(listOf(1L, 2L))) .thenReturn(Single.just(listOf(1L, 2L)))
whenever(sessionManager.userName).thenReturn("Test") whenever(sessionManager.userName).thenReturn("Test")
whenever(mediaClient.getMediaListForUser(anyString())).thenReturn( whenever(mediaClient.getMediaListForUser(anyString()))
Single.just(listOf(mock(Media::class.java))) .thenReturn(Single.just(listOf(media())))
)
contributionBoundaryCallback.onItemAtFrontLoaded(mock(Contribution::class.java)) contributionBoundaryCallback.onItemAtFrontLoaded(mock(Contribution::class.java))
verify(repository).save(anyList()); verify(repository).save(anyList());
verify(mediaClient).getMediaListForUser(anyString()); verify(mediaClient).getMediaListForUser(anyString());
@ -97,7 +94,7 @@ class ContributionBoundaryCallbackTest {
.thenReturn(Single.just(listOf(1L, 2L))) .thenReturn(Single.just(listOf(1L, 2L)))
whenever(sessionManager.userName).thenReturn("Test") whenever(sessionManager.userName).thenReturn("Test")
whenever(mediaClient.getMediaListForUser(anyString())).thenReturn( whenever(mediaClient.getMediaListForUser(anyString())).thenReturn(
Single.just(listOf(mock(Media::class.java))) Single.just(listOf(media()))
) )
contributionBoundaryCallback.fetchContributions() contributionBoundaryCallback.fetchContributions()
verify(repository).save(anyList()); verify(repository).save(anyList());

View file

@ -123,7 +123,7 @@ class DeleteHelperTest {
.thenReturn(Observable.just(true)) .thenReturn(Observable.just(true))
whenever(media.displayTitle).thenReturn("Test file") whenever(media.displayTitle).thenReturn("Test file")
media.filename ="Test file.jpg" whenever(media.filename).thenReturn("Test file.jpg")
whenever(media.creator).thenReturn(null) whenever(media.creator).thenReturn(null)

View file

@ -1,10 +1,10 @@
package fr.free.nrw.commons.review package fr.free.nrw.commons.review
import com.nhaarman.mockitokotlin2.whenever
import fr.free.nrw.commons.Media import fr.free.nrw.commons.Media
import fr.free.nrw.commons.media.MediaClient import fr.free.nrw.commons.media.MediaClient
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.Single import io.reactivex.Single
import junit.framework.Assert.assertNotNull
import junit.framework.Assert.assertNull import junit.framework.Assert.assertNull
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Before import org.junit.Before
@ -61,7 +61,7 @@ class ReviewHelperTest {
.thenReturn(Observable.just(mockResponse)) .thenReturn(Observable.just(mockResponse))
val media = mock(Media::class.java) val media = mock(Media::class.java)
media.filename="File:Test.jpg" whenever(media.filename).thenReturn("Test file.jpg")
`when`(mediaClient?.getMedia(ArgumentMatchers.anyString())) `when`(mediaClient?.getMedia(ArgumentMatchers.anyString()))
.thenReturn(Single.just(media)) .thenReturn(Single.just(media))
} }

View file

@ -2,6 +2,9 @@ package fr.free.nrw.commons.upload
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.whenever
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.contributions.Contribution import fr.free.nrw.commons.contributions.Contribution
import fr.free.nrw.commons.kvstore.JsonKvStore import fr.free.nrw.commons.kvstore.JsonKvStore
@ -47,7 +50,9 @@ class UploadControllerTest {
@Test @Test
fun startUpload() { fun startUpload() {
val contribution = mock(Contribution::class.java) val contribution = mock(Contribution::class.java)
`when`(contribution.getCreator()).thenReturn("Creator") val media = mock<Media>()
whenever(contribution.media).thenReturn(media)
whenever(media.creator).thenReturn("Creator")
uploadController!!.startUpload(contribution) uploadController!!.startUpload(contribution)
} }
} }