mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-29 05:43:55 +01:00
* Edited Project.xml to make indent size 4 * Changed files with 2 space indentation to use 4 space indentation * Edited Project.xml to make indent size 4 * changed files with 2 space indent to 4 space indent * fix :Back Pressed Event not work in Explore tab when user not login (#4404) * fix :Back Pressed Event not work in Explore tab * minor changes * fix :Upload count or number of contribution does not get updated when media is successful uploaded (#4399) * * fix:Number of Contributions not updated * Add javadocs * minor changes * made minor changes * String was nonsense and untranslatible, fixed (#4466) * Ability to show captions and descriptions in all entered languages (#4355) * implement Ability to show captions and descriptions in all entered languages *Add Javadoc * handle Back event of fragment(mediaDetailFragment) * fix minor bugs * add internationalization * revert previous changes * fix visibility bug * resolve conflict Co-authored-by: Prince kushwaha <65972015+Prince-kushwaha@users.noreply.github.com> Co-authored-by: neslihanturan <tur.neslihan@gmail.com>
This commit is contained in:
parent
b202f553f0
commit
ca9f6f5e47
36 changed files with 3047 additions and 2988 deletions
|
|
@ -19,43 +19,44 @@ import timber.log.Timber;
|
|||
@Singleton
|
||||
public class WikiBaseClient {
|
||||
|
||||
private final WikiBaseInterface wikiBaseInterface;
|
||||
private final CsrfTokenClient csrfTokenClient;
|
||||
private final WikiBaseInterface wikiBaseInterface;
|
||||
private final CsrfTokenClient csrfTokenClient;
|
||||
|
||||
@Inject
|
||||
public WikiBaseClient(WikiBaseInterface wikiBaseInterface,
|
||||
@Named(NAMED_COMMONS_CSRF) CsrfTokenClient csrfTokenClient) {
|
||||
this.wikiBaseInterface = wikiBaseInterface;
|
||||
this.csrfTokenClient = csrfTokenClient;
|
||||
}
|
||||
@Inject
|
||||
public WikiBaseClient(WikiBaseInterface wikiBaseInterface,
|
||||
@Named(NAMED_COMMONS_CSRF) CsrfTokenClient csrfTokenClient) {
|
||||
this.wikiBaseInterface = wikiBaseInterface;
|
||||
this.csrfTokenClient = csrfTokenClient;
|
||||
}
|
||||
|
||||
public Observable<Boolean> postEditEntity(String fileEntityId, String data) {
|
||||
return csrfToken()
|
||||
.switchMap(editToken -> wikiBaseInterface.postEditEntity(fileEntityId, editToken, data)
|
||||
.map(response -> (response.getSuccessVal() == 1)));
|
||||
}
|
||||
public Observable<Boolean> postEditEntity(String fileEntityId, String data) {
|
||||
return csrfToken()
|
||||
.switchMap(editToken -> wikiBaseInterface.postEditEntity(fileEntityId, editToken, data)
|
||||
.map(response -> (response.getSuccessVal() == 1)));
|
||||
}
|
||||
|
||||
public Observable<Long> getFileEntityId(UploadResult uploadResult) {
|
||||
return wikiBaseInterface.getFileEntityId(uploadResult.createCanonicalFileName())
|
||||
.map(response -> (long) (response.query().pages().get(0).pageId()));
|
||||
}
|
||||
public Observable<Long> getFileEntityId(UploadResult uploadResult) {
|
||||
return wikiBaseInterface.getFileEntityId(uploadResult.createCanonicalFileName())
|
||||
.map(response -> (long) (response.query().pages().get(0).pageId()));
|
||||
}
|
||||
|
||||
public Observable<MwPostResponse> addLabelstoWikidata(long fileEntityId,
|
||||
String languageCode, String captionValue) {
|
||||
return csrfToken()
|
||||
.switchMap(editToken -> wikiBaseInterface
|
||||
.addLabelstoWikidata(PAGE_ID_PREFIX + fileEntityId, editToken, languageCode, captionValue));
|
||||
public Observable<MwPostResponse> addLabelstoWikidata(long fileEntityId,
|
||||
String languageCode, String captionValue) {
|
||||
return csrfToken()
|
||||
.switchMap(editToken -> wikiBaseInterface
|
||||
.addLabelstoWikidata(PAGE_ID_PREFIX + fileEntityId, editToken, languageCode,
|
||||
captionValue));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Observable<String> csrfToken() {
|
||||
return Observable.fromCallable(() -> {
|
||||
try {
|
||||
return csrfTokenClient.getTokenBlocking();
|
||||
} catch (Throwable throwable) {
|
||||
Timber.e(throwable);
|
||||
return "";
|
||||
}
|
||||
});
|
||||
}
|
||||
private Observable<String> csrfToken() {
|
||||
return Observable.fromCallable(() -> {
|
||||
try {
|
||||
return csrfTokenClient.getTokenBlocking();
|
||||
} catch (Throwable throwable) {
|
||||
Timber.e(throwable);
|
||||
return "";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,32 +15,33 @@ import org.wikipedia.wikidata.Statement_partial;
|
|||
public class WikidataClient {
|
||||
|
||||
|
||||
private final WikidataInterface wikidataInterface;
|
||||
private final Gson gson;
|
||||
private final WikidataInterface wikidataInterface;
|
||||
private final Gson gson;
|
||||
|
||||
@Inject
|
||||
public WikidataClient(WikidataInterface wikidataInterface, final Gson gson) {
|
||||
this.wikidataInterface = wikidataInterface;
|
||||
this.gson = gson;
|
||||
}
|
||||
@Inject
|
||||
public WikidataClient(WikidataInterface wikidataInterface, final Gson gson) {
|
||||
this.wikidataInterface = wikidataInterface;
|
||||
this.gson = gson;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create wikidata claim to add P18 value
|
||||
*
|
||||
* @return revisionID of the edit
|
||||
*/
|
||||
Observable<Long> setClaim(Statement_partial claim, String tags) {
|
||||
return getCsrfToken()
|
||||
.flatMap(csrfToken -> wikidataInterface.postSetClaim(gson.toJson(claim), tags, csrfToken))
|
||||
.map(mwPostResponse -> mwPostResponse.getPageinfo().getLastrevid());
|
||||
}
|
||||
/**
|
||||
* Create wikidata claim to add P18 value
|
||||
*
|
||||
* @return revisionID of the edit
|
||||
*/
|
||||
Observable<Long> setClaim(Statement_partial claim, String tags) {
|
||||
return getCsrfToken()
|
||||
.flatMap(
|
||||
csrfToken -> wikidataInterface.postSetClaim(gson.toJson(claim), tags, csrfToken))
|
||||
.map(mwPostResponse -> mwPostResponse.getPageinfo().getLastrevid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get csrf token for wikidata edit
|
||||
*/
|
||||
@NotNull
|
||||
private Observable<String> getCsrfToken() {
|
||||
return wikidataInterface.getCsrfToken()
|
||||
.map(mwQueryResponse -> mwQueryResponse.query().csrfToken());
|
||||
}
|
||||
/**
|
||||
* Get csrf token for wikidata edit
|
||||
*/
|
||||
@NotNull
|
||||
private Observable<String> getCsrfToken() {
|
||||
return wikidataInterface.getCsrfToken()
|
||||
.map(mwQueryResponse -> mwQueryResponse.query().csrfToken());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,169 +44,172 @@ import timber.log.Timber;
|
|||
@Singleton
|
||||
public class WikidataEditService {
|
||||
|
||||
public static final String COMMONS_APP_TAG = "wikimedia-commons-app";
|
||||
public static final String COMMONS_APP_TAG = "wikimedia-commons-app";
|
||||
|
||||
private final Context context;
|
||||
private final WikidataEditListener wikidataEditListener;
|
||||
private final JsonKvStore directKvStore;
|
||||
private final WikiBaseClient wikiBaseClient;
|
||||
private final WikidataClient wikidataClient;
|
||||
private final Gson gson;
|
||||
private final Context context;
|
||||
private final WikidataEditListener wikidataEditListener;
|
||||
private final JsonKvStore directKvStore;
|
||||
private final WikiBaseClient wikiBaseClient;
|
||||
private final WikidataClient wikidataClient;
|
||||
private final Gson gson;
|
||||
|
||||
@Inject
|
||||
public WikidataEditService(final Context context,
|
||||
final WikidataEditListener wikidataEditListener,
|
||||
@Named("default_preferences") final JsonKvStore directKvStore,
|
||||
final WikiBaseClient wikiBaseClient,
|
||||
final WikidataClient wikidataClient, final Gson gson) {
|
||||
this.context = context;
|
||||
this.wikidataEditListener = wikidataEditListener;
|
||||
this.directKvStore = directKvStore;
|
||||
this.wikiBaseClient = wikiBaseClient;
|
||||
this.wikidataClient = wikidataClient;
|
||||
this.gson = gson;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the wikibase entity by adding DEPICTS property. Adding DEPICTS property requires call to
|
||||
* the wikibase API to set tag against the entity.
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
private Observable<Boolean> addDepictsProperty(final String fileEntityId,
|
||||
final WikidataItem depictedItem) {
|
||||
|
||||
final EditClaim data = editClaim(
|
||||
ConfigUtils.isBetaFlavour() ? "Q10" // Wikipedia:Sandbox (Q10)
|
||||
: depictedItem.getId()
|
||||
);
|
||||
|
||||
return wikiBaseClient.postEditEntity(PAGE_ID_PREFIX + fileEntityId, gson.toJson(data))
|
||||
.doOnNext(success -> {
|
||||
if (success) {
|
||||
Timber.d("DEPICTS property was set successfully for %s", fileEntityId);
|
||||
} else {
|
||||
Timber.d("Unable to set DEPICTS property for %s", fileEntityId);
|
||||
}
|
||||
})
|
||||
.doOnError(throwable -> {
|
||||
Timber.e(throwable, "Error occurred while setting DEPICTS property");
|
||||
ViewUtil.showLongToast(context, throwable.toString());
|
||||
})
|
||||
.subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
private EditClaim editClaim(final String entityId) {
|
||||
return EditClaim.from(entityId, WikidataProperties.DEPICTS.getPropertyName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a success toast when the edit is made successfully
|
||||
*/
|
||||
private void showSuccessToast(final String wikiItemName) {
|
||||
final String successStringTemplate = context.getString(R.string.successful_wikidata_edit);
|
||||
final String successMessage = String
|
||||
.format(Locale.getDefault(), successStringTemplate, wikiItemName);
|
||||
ViewUtil.showLongToast(context, successMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds label to Wikidata using the fileEntityId and the edit token, obtained from
|
||||
* csrfTokenClient
|
||||
*
|
||||
* @param fileEntityId
|
||||
* @return
|
||||
*/
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private Observable<Boolean> addCaption(final long fileEntityId, final String languageCode,
|
||||
final String captionValue) {
|
||||
return wikiBaseClient.addLabelstoWikidata(fileEntityId, languageCode, captionValue)
|
||||
.doOnNext(mwPostResponse -> onAddCaptionResponse(fileEntityId, mwPostResponse))
|
||||
.doOnError(throwable -> {
|
||||
Timber.e(throwable, "Error occurred while setting Captions");
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure));
|
||||
})
|
||||
.map(mwPostResponse -> mwPostResponse != null);
|
||||
}
|
||||
|
||||
private void onAddCaptionResponse(Long fileEntityId, MwPostResponse response) {
|
||||
if (response != null) {
|
||||
Timber.d("Caption successfully set, revision id = %s", response);
|
||||
} else {
|
||||
Timber.d("Error occurred while setting Captions, fileEntityId = %s", fileEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
public Long createClaim(@Nullable final WikidataPlace wikidataPlace, final String fileName, final
|
||||
Map<String, String> captions) {
|
||||
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 null;
|
||||
}
|
||||
return addImageAndMediaLegends(wikidataPlace, fileName, captions);
|
||||
}
|
||||
|
||||
public Long addImageAndMediaLegends(final WikidataItem wikidataItem, final String fileName,
|
||||
final Map<String, String> captions) {
|
||||
final Snak_partial p18 = new Snak_partial("value", WikidataProperties.IMAGE.getPropertyName(),
|
||||
new ValueString(fileName.replace("File:", "")));
|
||||
|
||||
final List<Snak_partial> snaks = new ArrayList<>();
|
||||
for (final Map.Entry<String, String> entry : captions.entrySet()) {
|
||||
snaks.add(new Snak_partial("value",
|
||||
WikidataProperties.MEDIA_LEGENDS.getPropertyName(), new DataValue.MonoLingualText(
|
||||
new WikiBaseMonolingualTextValue(entry.getValue(), entry.getKey()))));
|
||||
@Inject
|
||||
public WikidataEditService(final Context context,
|
||||
final WikidataEditListener wikidataEditListener,
|
||||
@Named("default_preferences") final JsonKvStore directKvStore,
|
||||
final WikiBaseClient wikiBaseClient,
|
||||
final WikidataClient wikidataClient, final Gson gson) {
|
||||
this.context = context;
|
||||
this.wikidataEditListener = wikidataEditListener;
|
||||
this.directKvStore = directKvStore;
|
||||
this.wikiBaseClient = wikiBaseClient;
|
||||
this.wikidataClient = wikidataClient;
|
||||
this.gson = gson;
|
||||
}
|
||||
|
||||
final String id = wikidataItem.getId() + "$" + UUID.randomUUID().toString();
|
||||
final Statement_partial claim = new Statement_partial(p18, "statement", "normal", id,
|
||||
Collections.singletonMap(WikidataProperties.MEDIA_LEGENDS.getPropertyName(), snaks),
|
||||
Arrays.asList(WikidataProperties.MEDIA_LEGENDS.getPropertyName()));
|
||||
/**
|
||||
* Edits the wikibase entity by adding DEPICTS property. Adding DEPICTS property requires call
|
||||
* to the wikibase API to set tag against the entity.
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
private Observable<Boolean> addDepictsProperty(final String fileEntityId,
|
||||
final WikidataItem depictedItem) {
|
||||
|
||||
return wikidataClient.setClaim(claim, COMMONS_APP_TAG).blockingSingle();
|
||||
}
|
||||
|
||||
public void handleImageClaimResult(final WikidataItem wikidataItem, final Long revisionId) {
|
||||
if (revisionId != null) {
|
||||
if (wikidataEditListener != null) {
|
||||
wikidataEditListener.onSuccessfulWikidataEdit();
|
||||
}
|
||||
showSuccessToast(wikidataItem.getName());
|
||||
} else {
|
||||
Timber.d("Unable to make wiki data edit for entity %s", wikidataItem);
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure));
|
||||
}
|
||||
}
|
||||
|
||||
public Observable addDepictionsAndCaptions(final UploadResult uploadResult, final Contribution contribution) {
|
||||
return wikiBaseClient.getFileEntityId(uploadResult)
|
||||
.doOnError(throwable -> {
|
||||
Timber.e(throwable, "Error occurred while getting EntityID to set DEPICTS property");
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure));
|
||||
})
|
||||
.switchMap(fileEntityId -> {
|
||||
if (fileEntityId != null) {
|
||||
Timber.d("EntityId for image was received successfully: %s", fileEntityId);
|
||||
return Observable.concat(
|
||||
depictionEdits(contribution, fileEntityId),
|
||||
captionEdits(contribution, fileEntityId)
|
||||
);
|
||||
} else {
|
||||
Timber.d("Error acquiring EntityId for image: %s", uploadResult);
|
||||
return Observable.empty();
|
||||
}
|
||||
}
|
||||
final EditClaim data = editClaim(
|
||||
ConfigUtils.isBetaFlavour() ? "Q10" // Wikipedia:Sandbox (Q10)
|
||||
: depictedItem.getId()
|
||||
);
|
||||
}
|
||||
|
||||
private Observable<Boolean> captionEdits(Contribution contribution, Long fileEntityId) {
|
||||
return Observable.fromIterable(contribution.getMedia().getCaptions().entrySet())
|
||||
.concatMap(entry -> addCaption(fileEntityId, entry.getKey(), entry.getValue()));
|
||||
}
|
||||
return wikiBaseClient.postEditEntity(PAGE_ID_PREFIX + fileEntityId, gson.toJson(data))
|
||||
.doOnNext(success -> {
|
||||
if (success) {
|
||||
Timber.d("DEPICTS property was set successfully for %s", fileEntityId);
|
||||
} else {
|
||||
Timber.d("Unable to set DEPICTS property for %s", fileEntityId);
|
||||
}
|
||||
})
|
||||
.doOnError(throwable -> {
|
||||
Timber.e(throwable, "Error occurred while setting DEPICTS property");
|
||||
ViewUtil.showLongToast(context, throwable.toString());
|
||||
})
|
||||
.subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
private Observable<Boolean> depictionEdits(Contribution contribution, Long fileEntityId) {
|
||||
return Observable.fromIterable(contribution.getDepictedItems())
|
||||
.concatMap(wikidataItem -> addDepictsProperty(fileEntityId.toString(), wikidataItem));
|
||||
}
|
||||
private EditClaim editClaim(final String entityId) {
|
||||
return EditClaim.from(entityId, WikidataProperties.DEPICTS.getPropertyName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a success toast when the edit is made successfully
|
||||
*/
|
||||
private void showSuccessToast(final String wikiItemName) {
|
||||
final String successStringTemplate = context.getString(R.string.successful_wikidata_edit);
|
||||
final String successMessage = String
|
||||
.format(Locale.getDefault(), successStringTemplate, wikiItemName);
|
||||
ViewUtil.showLongToast(context, successMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds label to Wikidata using the fileEntityId and the edit token, obtained from
|
||||
* csrfTokenClient
|
||||
*
|
||||
* @param fileEntityId
|
||||
* @return
|
||||
*/
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private Observable<Boolean> addCaption(final long fileEntityId, final String languageCode,
|
||||
final String captionValue) {
|
||||
return wikiBaseClient.addLabelstoWikidata(fileEntityId, languageCode, captionValue)
|
||||
.doOnNext(mwPostResponse -> onAddCaptionResponse(fileEntityId, mwPostResponse))
|
||||
.doOnError(throwable -> {
|
||||
Timber.e(throwable, "Error occurred while setting Captions");
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure));
|
||||
})
|
||||
.map(mwPostResponse -> mwPostResponse != null);
|
||||
}
|
||||
|
||||
private void onAddCaptionResponse(Long fileEntityId, MwPostResponse response) {
|
||||
if (response != null) {
|
||||
Timber.d("Caption successfully set, revision id = %s", response);
|
||||
} else {
|
||||
Timber.d("Error occurred while setting Captions, fileEntityId = %s", fileEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
public Long createClaim(@Nullable final WikidataPlace wikidataPlace, final String fileName,
|
||||
final Map<String, String> captions) {
|
||||
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 null;
|
||||
}
|
||||
return addImageAndMediaLegends(wikidataPlace, fileName, captions);
|
||||
}
|
||||
|
||||
public Long addImageAndMediaLegends(final WikidataItem wikidataItem, final String fileName,
|
||||
final Map<String, String> captions) {
|
||||
final Snak_partial p18 = new Snak_partial("value",
|
||||
WikidataProperties.IMAGE.getPropertyName(),
|
||||
new ValueString(fileName.replace("File:", "")));
|
||||
|
||||
final List<Snak_partial> snaks = new ArrayList<>();
|
||||
for (final Map.Entry<String, String> entry : captions.entrySet()) {
|
||||
snaks.add(new Snak_partial("value",
|
||||
WikidataProperties.MEDIA_LEGENDS.getPropertyName(), new DataValue.MonoLingualText(
|
||||
new WikiBaseMonolingualTextValue(entry.getValue(), entry.getKey()))));
|
||||
}
|
||||
|
||||
final String id = wikidataItem.getId() + "$" + UUID.randomUUID().toString();
|
||||
final Statement_partial claim = new Statement_partial(p18, "statement", "normal", id,
|
||||
Collections.singletonMap(WikidataProperties.MEDIA_LEGENDS.getPropertyName(), snaks),
|
||||
Arrays.asList(WikidataProperties.MEDIA_LEGENDS.getPropertyName()));
|
||||
|
||||
return wikidataClient.setClaim(claim, COMMONS_APP_TAG).blockingSingle();
|
||||
}
|
||||
|
||||
public void handleImageClaimResult(final WikidataItem wikidataItem, final Long revisionId) {
|
||||
if (revisionId != null) {
|
||||
if (wikidataEditListener != null) {
|
||||
wikidataEditListener.onSuccessfulWikidataEdit();
|
||||
}
|
||||
showSuccessToast(wikidataItem.getName());
|
||||
} else {
|
||||
Timber.d("Unable to make wiki data edit for entity %s", wikidataItem);
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure));
|
||||
}
|
||||
}
|
||||
|
||||
public Observable addDepictionsAndCaptions(final UploadResult uploadResult,
|
||||
final Contribution contribution) {
|
||||
return wikiBaseClient.getFileEntityId(uploadResult)
|
||||
.doOnError(throwable -> {
|
||||
Timber
|
||||
.e(throwable, "Error occurred while getting EntityID to set DEPICTS property");
|
||||
ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure));
|
||||
})
|
||||
.switchMap(fileEntityId -> {
|
||||
if (fileEntityId != null) {
|
||||
Timber.d("EntityId for image was received successfully: %s", fileEntityId);
|
||||
return Observable.concat(
|
||||
depictionEdits(contribution, fileEntityId),
|
||||
captionEdits(contribution, fileEntityId)
|
||||
);
|
||||
} else {
|
||||
Timber.d("Error acquiring EntityId for image: %s", uploadResult);
|
||||
return Observable.empty();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private Observable<Boolean> captionEdits(Contribution contribution, Long fileEntityId) {
|
||||
return Observable.fromIterable(contribution.getMedia().getCaptions().entrySet())
|
||||
.concatMap(entry -> addCaption(fileEntityId, entry.getKey(), entry.getValue()));
|
||||
}
|
||||
|
||||
private Observable<Boolean> depictionEdits(Contribution contribution, Long fileEntityId) {
|
||||
return Observable.fromIterable(contribution.getDepictedItems())
|
||||
.concatMap(wikidataItem -> addDepictsProperty(fileEntityId.toString(), wikidataItem));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue