Fix 4615: Option for editing caption and description (#4672)

* DescriptionEditHelper implemented

* Description extracted

* Description editable

* No description condition handled

* Code cleanup

* Added javadocs

* toolbar added

* API call done

* Caption edit available

* Progress dialog added

* Log

* Problem with ButterKnife

* Caption is editable

* Removed unused import

* Manifest file reverted

* Manifest file reverted

* Manifest file reverted

* View binding added

* Post operation test added

* Java docs added

* Java docs added

* MediaDetailFragment unit tests added

* Test added
This commit is contained in:
Ayan Sarkar 2021-12-07 01:20:54 +05:30 committed by GitHub
parent e910b1d14f
commit 0269894c64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 855 additions and 14 deletions

View file

@ -50,4 +50,9 @@ class MediaDataExtractor @Inject constructor(private val mediaClient: MediaClien
}
fun getHtmlOfPage(title: String) = mediaClient.getPageHtml(title);
/**
* Fetches wikitext from mediaClient
*/
fun getCurrentWikiText(title: String) = mediaClient.getCurrentWikiText(title);
}

View file

@ -64,6 +64,24 @@ class PageEditClient(
}
}
/**
* Set new labels to Wikibase server of commons
* @param summary Edit summary
* @param title Title of the page to edit
* @param language Corresponding language of label
* @param value label
* @return 1 when the edit was successful
*/
fun setCaptions(summary: String, title: String,
language: String, value: String) : Observable<Int>{
return try {
pageEditInterface.postCaptions(summary, title, language,
value, csrfTokenClient.tokenBlocking).map { it.success }
} catch (throwable: Throwable) {
Observable.just(0)
}
}
/**
* Get whole WikiText of required file
* @param title : Name of the file

View file

@ -5,6 +5,7 @@ import io.reactivex.Single
import org.wikipedia.dataclient.Service
import org.wikipedia.dataclient.mwapi.MwQueryResponse
import org.wikipedia.edit.Edit
import org.wikipedia.wikidata.Entities
import retrofit2.http.*
/**
@ -73,6 +74,18 @@ interface PageEditInterface {
@Field("token") token: String
): Observable<Edit>
@FormUrlEncoded
@Headers("Cache-Control: no-cache")
@POST(Service.MW_API_PREFIX + "action=wbsetlabel&format=json&site=commonswiki&formatversion=2")
fun postCaptions(
@Field("summary") summary: String,
@Field("title") title: String,
@Field("language") language: String,
@Field("value") value: String,
@Field("token") token: String
): Observable<Entities>
/**
* Get wiki text for provided file names
* @param titles : Name of the file

View file

@ -0,0 +1,181 @@
package fr.free.nrw.commons.description
import android.app.ProgressDialog
import android.content.Intent
import android.os.Bundle
import android.os.Parcelable
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import fr.free.nrw.commons.R
import fr.free.nrw.commons.databinding.ActivityDescriptionEditBinding
import fr.free.nrw.commons.description.EditDescriptionConstants.LIST_OF_DESCRIPTION_AND_CAPTION
import fr.free.nrw.commons.description.EditDescriptionConstants.UPDATED_WIKITEXT
import fr.free.nrw.commons.description.EditDescriptionConstants.WIKITEXT
import fr.free.nrw.commons.kvstore.JsonKvStore
import fr.free.nrw.commons.settings.Prefs
import fr.free.nrw.commons.upload.UploadMediaDetail
import fr.free.nrw.commons.upload.UploadMediaDetailAdapter
import fr.free.nrw.commons.utils.DialogUtil.showAlertDialog
import java.util.*
import javax.inject.Inject
import javax.inject.Named
/**
* Activity for populating and editing existing description and caption
*/
class DescriptionEditActivity : AppCompatActivity(), UploadMediaDetailAdapter.EventListener {
/**
* Adapter for showing UploadMediaDetail in the activity
*/
private lateinit var uploadMediaDetailAdapter: UploadMediaDetailAdapter
/**
* For getting default preference
*/
@JvmField
@Inject
@Named("default_preferences")
var defaultKvStore: JsonKvStore? = null
/**
* Recyclerview for recycling data in views
*/
@JvmField
var rvDescriptions: RecyclerView? = null
/**
* Current wikitext
*/
var wikiText: String? = null
/**
* For showing progress dialog
*/
private var progressDialog: ProgressDialog? = null
private lateinit var binding: ActivityDescriptionEditBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDescriptionEditBinding.inflate(layoutInflater)
setContentView(binding.root)
val bundle = intent.extras
val descriptionAndCaptions: ArrayList<UploadMediaDetail> =
bundle!!.getParcelableArrayList(LIST_OF_DESCRIPTION_AND_CAPTION)!!
wikiText = bundle.getString(WIKITEXT)
initRecyclerView(descriptionAndCaptions)
binding.btnAddDescription.setOnClickListener(::onButtonAddDescriptionClicked)
binding.btnEditSubmit.setOnClickListener(::onSubmitButtonClicked)
binding.toolbarBackButton.setOnClickListener(::onBackButtonClicked)
}
/**
* Initializes the RecyclerView
* @param descriptionAndCaptions list of description and caption
*/
private fun initRecyclerView(descriptionAndCaptions: ArrayList<UploadMediaDetail>?) {
uploadMediaDetailAdapter = UploadMediaDetailAdapter(
defaultKvStore?.getString(Prefs.DESCRIPTION_LANGUAGE, ""),
descriptionAndCaptions)
uploadMediaDetailAdapter.setCallback { titleStringID: Int, messageStringId: Int ->
showInfoAlert(
titleStringID,
messageStringId
)
}
uploadMediaDetailAdapter.setEventListener(this)
rvDescriptions = binding.rvDescriptionsCaptions
rvDescriptions!!.layoutManager = LinearLayoutManager(this)
rvDescriptions!!.adapter = uploadMediaDetailAdapter
}
/**
* show dialog with info
* @param titleStringID Title ID
* @param messageStringId Message ID
*/
private fun showInfoAlert(titleStringID: Int, messageStringId: Int) {
showAlertDialog(
this, getString(titleStringID),
getString(messageStringId), getString(android.R.string.ok),
null, true
)
}
override fun onPrimaryCaptionTextChange(isNotEmpty: Boolean) {}
private fun onBackButtonClicked(view: View) {
onBackPressed()
}
private fun onButtonAddDescriptionClicked(view: View) {
val uploadMediaDetail = UploadMediaDetail()
uploadMediaDetail.isManuallyAdded = true //This was manually added by the user
uploadMediaDetailAdapter.addDescription(uploadMediaDetail)
rvDescriptions!!.smoothScrollToPosition(uploadMediaDetailAdapter.itemCount - 1)
}
private fun onSubmitButtonClicked(view: View) {
showLoggingProgressBar()
val uploadMediaDetails = uploadMediaDetailAdapter.items
updateDescription(uploadMediaDetails)
finish()
}
/**
* Updates newly added descriptions in the wikiText and send to calling fragment
* @param uploadMediaDetails descriptions and captions
*/
private fun updateDescription(uploadMediaDetails: List<UploadMediaDetail?>) {
var descriptionIndex = wikiText!!.indexOf("description=")
if (descriptionIndex == -1) {
descriptionIndex = wikiText!!.indexOf("Description=")
}
val buffer = StringBuilder()
if (descriptionIndex != -1) {
val descriptionStart = wikiText!!.substring(0, descriptionIndex + 12)
val descriptionToEnd = wikiText!!.substring(descriptionIndex + 12)
val descriptionEndIndex = descriptionToEnd.indexOf("\n")
val descriptionEnd = wikiText!!.substring(
descriptionStart.length
+ descriptionEndIndex
)
buffer.append(descriptionStart)
for (i in uploadMediaDetails.indices) {
val uploadDetails = uploadMediaDetails[i]
if (uploadDetails!!.descriptionText != "") {
buffer.append("{{")
buffer.append(uploadDetails.languageCode)
buffer.append("|1=")
buffer.append(uploadDetails.descriptionText)
buffer.append("}}, ")
}
}
buffer.deleteCharAt(buffer.length - 1)
buffer.deleteCharAt(buffer.length - 1)
buffer.append(descriptionEnd)
}
val returningIntent = Intent()
returningIntent.putExtra(UPDATED_WIKITEXT, buffer.toString())
returningIntent.putParcelableArrayListExtra(
LIST_OF_DESCRIPTION_AND_CAPTION,
uploadMediaDetails as ArrayList<out Parcelable?>
)
setResult(RESULT_OK, returningIntent)
finish()
}
private fun showLoggingProgressBar() {
progressDialog = ProgressDialog(this)
progressDialog!!.isIndeterminate = true
progressDialog!!.setTitle(getString(R.string.updating_caption_title))
progressDialog!!.setMessage(getString(R.string.updating_caption_message))
progressDialog!!.setCanceledOnTouchOutside(false)
progressDialog!!.show()
}
}

View file

@ -0,0 +1,137 @@
package fr.free.nrw.commons.description;
import static fr.free.nrw.commons.notification.NotificationHelper.NOTIFICATION_EDIT_DESCRIPTION;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.actions.PageEditClient;
import fr.free.nrw.commons.notification.NotificationHelper;
import io.reactivex.Single;
import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Named;
import timber.log.Timber;
/**
* Helper class for edit and update given descriptions and showing notification upgradation
*/
public class DescriptionEditHelper {
/**
* notificationHelper: helps creating notification
*/
private final NotificationHelper notificationHelper;
/**
* * pageEditClient: methods provided by this member posts the edited descriptions
* to the Media wiki api
*/
public final PageEditClient pageEditClient;
@Inject
public DescriptionEditHelper(final NotificationHelper notificationHelper,
@Named("commons-page-edit") final PageEditClient pageEditClient) {
this.notificationHelper = notificationHelper;
this.pageEditClient = pageEditClient;
}
/**
* Replaces new descriptions
*
* @param context context
* @param media to be added
* @param appendText to be added
* @return Observable<Boolean>
*/
public Single<Boolean> addDescription(final Context context, final Media media,
final String appendText) {
Timber.d("thread is description adding %s", Thread.currentThread().getName());
final String summary = "Updating Description";
return pageEditClient.edit(Objects.requireNonNull(media.getFilename()),
appendText, summary)
.flatMapSingle(result -> Single.just(showDescriptionEditNotification(context,
media, result)))
.firstOrError();
}
/**
* Adds new captions
*
* @param context context
* @param media to be added
* @param language to be added
* @param value to be added
* @return Observable<Boolean>
*/
public Single<Boolean> addCaption(final Context context, final Media media,
final String language, final String value) {
Timber.d("thread is caption adding %s", Thread.currentThread().getName());
final String summary = "Updating Caption";
return pageEditClient.setCaptions(summary, Objects.requireNonNull(media.getFilename()),
language, value)
.flatMapSingle(result -> Single.just(showCaptionEditNotification(context,
media, result)))
.firstOrError();
}
/**
* Update captions and shows notification about captions update
* @param context to be added
* @param media to be added
* @param result to be added
* @return boolean
*/
private boolean showCaptionEditNotification(final Context context, final Media media,
final int result) {
final String message;
String title = context.getString(R.string.caption_edit_helper_show_edit_title);
if (result == 1) {
title += ": " + context
.getString(R.string.coordinates_edit_helper_show_edit_title_success);
message = context.getString(R.string.caption_edit_helper_show_edit_message);
} else {
title += ": " + context.getString(R.string.caption_edit_helper_show_edit_title);
message = context.getString(R.string.caption_edit_helper_edit_message_else) ;
}
final String urlForFile = BuildConfig.COMMONS_URL + "/wiki/" + media.getFilename();
final Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlForFile));
notificationHelper.showNotification(context, title, message, NOTIFICATION_EDIT_DESCRIPTION,
browserIntent);
return result == 1;
}
/**
* Update descriptions and shows notification about descriptions update
* @param context to be added
* @param media to be added
* @param result to be added
* @return boolean
*/
private boolean showDescriptionEditNotification(final Context context, final Media media,
final boolean result) {
final String message;
String title = context.getString(R.string.description_edit_helper_show_edit_title);
if (result) {
title += ": " + context
.getString(R.string.coordinates_edit_helper_show_edit_title_success);
message = context.getString(R.string.description_edit_helper_show_edit_message);
} else {
title += ": " + context.getString(R.string.description_edit_helper_show_edit_title);
message = context.getString(R.string.description_edit_helper_edit_message_else) ;
}
final String urlForFile = BuildConfig.COMMONS_URL + "/wiki/" + media.getFilename();
final Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlForFile));
notificationHelper.showNotification(context, title, message, NOTIFICATION_EDIT_DESCRIPTION,
browserIntent);
return result;
}
}

View file

@ -0,0 +1,10 @@
package fr.free.nrw.commons.description
/**
* For storing required constants for editing descriptions
*/
object EditDescriptionConstants {
const val LIST_OF_DESCRIPTION_AND_CAPTION = "description.descriptionAndCaption"
const val WIKITEXT = "description.wikiText"
const val UPDATED_WIKITEXT = "description.updatedWikiText";
}

View file

@ -157,6 +157,17 @@ class MediaClient @Inject constructor(
fun resetUserNameContinuation(userName: String) =
resetUserContinuation("user_", userName)
/**
* Get whole WikiText of required file
* @param title : Name of the file
* @return Observable<MwQueryResult>
*/
fun getCurrentWikiText(title: String): Single<String?> {
return mediaDetailInterface.getWikiText(title).map {
it.query()?.pages()?.get(0)?.revisions()?.get(0)?.content()
}
}
override fun responseMapper(
networkResult: Single<MwQueryResponse>,
key: String?

View file

@ -6,6 +6,9 @@ import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_NEEDING_CATEGORIES;
import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_UNCATEGORISED;
import static fr.free.nrw.commons.description.EditDescriptionConstants.LIST_OF_DESCRIPTION_AND_CAPTION;
import static fr.free.nrw.commons.description.EditDescriptionConstants.UPDATED_WIKITEXT;
import static fr.free.nrw.commons.description.EditDescriptionConstants.WIKITEXT;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
@ -71,18 +74,23 @@ import fr.free.nrw.commons.contributions.ContributionsFragment;
import fr.free.nrw.commons.coordinates.CoordinateEditHelper;
import fr.free.nrw.commons.delete.DeleteHelper;
import fr.free.nrw.commons.delete.ReasonBuilder;
import fr.free.nrw.commons.description.DescriptionEditActivity;
import fr.free.nrw.commons.description.DescriptionEditHelper;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.nearby.Label;
import fr.free.nrw.commons.profile.ProfileActivity;
import fr.free.nrw.commons.ui.widget.HtmlTextView;
import fr.free.nrw.commons.upload.UploadMediaDetail;
import fr.free.nrw.commons.utils.ViewUtilWrapper;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -99,6 +107,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
CategoryEditHelper.Callback {
private static final int REQUEST_CODE = 1001 ;
private static final int REQUEST_CODE_EDIT_DESCRIPTION = 1002 ;
private boolean editable;
private boolean isCategoryImage;
private MediaDetailPagerFragment.MediaDetailProvider detailProvider;
@ -136,6 +145,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
@Inject
CoordinateEditHelper coordinateEditHelper;
@Inject
DescriptionEditHelper descriptionEditHelper;
@Inject
ViewUtilWrapper viewUtil;
@Inject
CategoryClient categoryClient;
@ -225,6 +236,10 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
String descriptionHtmlCode;
@BindView(R.id.progressBarDeletion)
ProgressBar progressBarDeletion;
@BindView(R.id.progressBarEdit)
ProgressBar progressBarEditDescription;
@BindView(R.id.description_edit)
Button editDescription;
private ArrayList<String> categoryNames = new ArrayList<>();
private String categorySearchQuery;
@ -819,8 +834,155 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
.build(getActivity()), REQUEST_CODE);
}
@OnClick(R.id.description_edit)
public void onDescriptionEditClicked() {
progressBarEditDescription.setVisibility(VISIBLE);
editDescription.setVisibility(GONE);
getDescriptionList();
}
/**
* Get the coordinates and update the existing coordinates.
* Gets descriptions from wikitext
*/
private void getDescriptionList() {
compositeDisposable.add(mediaDataExtractor.getCurrentWikiText(
Objects.requireNonNull(media.getFilename()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::extractCaptionDescription, Timber::e));
}
/**
* Gets captions and descriptions and merge them according to language code and arranges it in a
* single list.
* Send the list to DescriptionEditActivity
* @param s wikitext
*/
private void extractCaptionDescription(final String s) {
final LinkedHashMap<String,String> descriptions = getDescriptions(s);
final LinkedHashMap<String,String> captions = getCaptionsList();
final ArrayList<UploadMediaDetail> descriptionAndCaptions = new ArrayList<>();
if(captions.size() >= descriptions.size()) {
for (final Map.Entry mapElement : captions.entrySet()) {
final String language = (String) mapElement.getKey();
if (descriptions.containsKey(language)) {
descriptionAndCaptions.add(
new UploadMediaDetail(language,
Objects.requireNonNull(descriptions.get(language)),
(String) mapElement.getValue())
);
} else {
descriptionAndCaptions.add(
new UploadMediaDetail(language, "",
(String) mapElement.getValue())
);
}
}
for (final Map.Entry mapElement : descriptions.entrySet()) {
final String language = (String) mapElement.getKey();
if (!captions.containsKey(language)) {
descriptionAndCaptions.add(
new UploadMediaDetail(language,
Objects.requireNonNull(descriptions.get(language)),
"")
);
}
}
} else {
for (final Map.Entry mapElement : descriptions.entrySet()) {
final String language = (String) mapElement.getKey();
if (captions.containsKey(language)) {
descriptionAndCaptions.add(
new UploadMediaDetail(language, (String) mapElement.getValue(),
Objects.requireNonNull(captions.get(language)))
);
} else {
descriptionAndCaptions.add(
new UploadMediaDetail(language, (String) mapElement.getValue(),
"")
);
}
}
for (final Map.Entry mapElement : captions.entrySet()) {
final String language = (String) mapElement.getKey();
if (!descriptions.containsKey(language)) {
descriptionAndCaptions.add(
new UploadMediaDetail(language,
"",
Objects.requireNonNull(descriptions.get(language)))
);
}
}
}
final Intent intent = new Intent(requireContext(), DescriptionEditActivity.class);
final Bundle bundle = new Bundle();
bundle.putParcelableArrayList(LIST_OF_DESCRIPTION_AND_CAPTION, descriptionAndCaptions);
bundle.putString(WIKITEXT, s);
intent.putExtras(bundle);
startActivityForResult(intent, REQUEST_CODE_EDIT_DESCRIPTION);
}
/**
* Filters descriptions from current wikiText and arranges it in LinkedHashmap according to the
* language code
* @param s wikitext
* @return LinkedHashMap<LanguageCode,Description>
*/
private LinkedHashMap<String,String> getDescriptions(String s) {
int descriptionIndex = s.indexOf("description=");
if(descriptionIndex == -1){
descriptionIndex = s.indexOf("Description=");
}
if( descriptionIndex == -1 ){
return new LinkedHashMap<>();
}
final String descriptionToEnd = s.substring(descriptionIndex+12);
final int descriptionEndIndex = descriptionToEnd.indexOf("\n");
final String description = s.substring(descriptionIndex+12, descriptionIndex+12+descriptionEndIndex);
final String[] arr = description.trim().split(",");
final LinkedHashMap<String,String> descriptionList = new LinkedHashMap<>();
if (!description.equals("")) {
for (final String string :
arr) {
final int startCode = string.indexOf("{{");
final int endCode = string.indexOf("|");
final String languageCode = string.substring(startCode + 2, endCode).trim();
final int startDescription = string.indexOf("=");
final int endDescription = string.indexOf("}}");
final String languageDescription = string
.substring(startDescription + 1, endDescription);
descriptionList.put(languageCode, languageDescription);
}
}
return descriptionList;
}
/**
* Gets list of caption and arranges it in a LinkedHashmap according to the language code
* @return LinkedHashMap<LanguageCode,Caption>
*/
private LinkedHashMap<String,String> getCaptionsList() {
final LinkedHashMap<String, String> captionList = new LinkedHashMap<>();
final Map<String, String> captions = media.getCaptions();
for (final Map.Entry<String, String> map : captions.entrySet()) {
final String language = map.getKey();
final String languageCaption = map.getValue();
captionList.put(language, languageCaption);
}
return captionList;
}
/**
* Get the result from another activity and act accordingly.
* @param requestCode
* @param resultCode
* @param data
@ -854,13 +1016,61 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
updateCoordinates(latitude, longitude, accuracy);
}
}
} else if (resultCode == RESULT_CANCELED) {
} else if (requestCode == REQUEST_CODE_EDIT_DESCRIPTION && resultCode == RESULT_OK) {
final String updatedWikiText = data.getStringExtra(UPDATED_WIKITEXT);
compositeDisposable.add(descriptionEditHelper.addDescription(getContext(), media,
updatedWikiText)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> {
Timber.d("Descriptions are added.");
}));
final ArrayList<UploadMediaDetail> uploadMediaDetails
= data.getParcelableArrayListExtra(LIST_OF_DESCRIPTION_AND_CAPTION);
LinkedHashMap<String, String> updatedCaptions = new LinkedHashMap<>();
for (UploadMediaDetail mediaDetail:
uploadMediaDetails) {
compositeDisposable.add(descriptionEditHelper.addCaption(getContext(), media,
mediaDetail.getLanguageCode(), mediaDetail.getCaptionText())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> {
updateCaptions(mediaDetail, updatedCaptions);
Timber.d("Caption is added.");
}));
}
progressBarEditDescription.setVisibility(GONE);
editDescription.setVisibility(VISIBLE);
} else if (requestCode == REQUEST_CODE && resultCode == RESULT_CANCELED) {
viewUtil.showShortToast(getContext(),
Objects.requireNonNull(getContext())
.getString(R.string.coordinates_picking_unsuccessful));
} else if (requestCode == REQUEST_CODE_EDIT_DESCRIPTION && resultCode == RESULT_CANCELED) {
progressBarEditDescription.setVisibility(GONE);
editDescription.setVisibility(VISIBLE);
viewUtil.showShortToast(getContext(),
Objects.requireNonNull(getContext())
.getString(R.string.descriptions_picking_unsuccessful));
}
}
/**
* Adds caption to the map and updates captions
* @param mediaDetail UploadMediaDetail
* @param updatedCaptions updated captionds
*/
private void updateCaptions(UploadMediaDetail mediaDetail,
LinkedHashMap<String, String> updatedCaptions) {
updatedCaptions.put(mediaDetail.getLanguageCode(), mediaDetail.getCaptionText());
media.setCaptions(updatedCaptions);
}
@OnClick(R.id.update_categories_button)
public void onUpdateCategoriesClicked() {
updateCategories(categoryEditSearchRecyclerViewAdapter.getNewCategories());

View file

@ -2,6 +2,8 @@ package fr.free.nrw.commons.media;
import io.reactivex.Observable;
import io.reactivex.Single;
import org.wikipedia.dataclient.Service;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import org.wikipedia.wikidata.Entities;
import retrofit2.Call;
import retrofit2.http.GET;
@ -35,4 +37,18 @@ public interface MediaDetailInterface {
*/
@GET("/w/api.php?action=wbgetentities&props=labels&format=json&languagefallback=1&sites=commonswiki")
Observable<Entities> getEntityForImage(@Query("languages") String language, @Query("ids") String wikibaseIdentifier);
/**
* Fetches current wikitext
* @param title file name
* @return Single<MwQueryResponse>
*/
@GET(
Service.MW_API_PREFIX +
"action=query&prop=revisions&rvprop=content|timestamp&rvlimit=1&converttitles="
)
Single<MwQueryResponse> getWikiText(
@Query("titles") String title
);
}

View file

@ -26,6 +26,7 @@ public class NotificationHelper {
public static final int NOTIFICATION_DELETE = 1;
public static final int NOTIFICATION_EDIT_CATEGORY = 2;
public static final int NOTIFICATION_EDIT_COORDINATES = 3;
public static final int NOTIFICATION_EDIT_DESCRIPTION = 4;
private NotificationManager notificationManager;
private NotificationCompat.Builder notificationBuilder;

View file

@ -1,10 +1,13 @@
package fr.free.nrw.commons.upload
import android.os.Parcelable
import fr.free.nrw.commons.nearby.Place
import kotlinx.android.parcel.Parcelize
/**
* Holds a description of an item being uploaded by [UploadActivity]
*/
@Parcelize
data class UploadMediaDetail constructor(
/**
* @return The language code ie. "en" or "fr"
@ -15,7 +18,7 @@ data class UploadMediaDetail constructor(
var languageCode: String? = null,
var descriptionText: String = "",
var captionText: String = ""
) {
) : Parcelable {
fun javaCopy() = copy()
constructor(place: Place) : this(

View file

@ -37,6 +37,13 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
this.savedLanguageValue = savedLanguageValue;
}
public UploadMediaDetailAdapter(final String savedLanguageValue,
List<UploadMediaDetail> uploadMediaDetails) {
this.uploadMediaDetails = uploadMediaDetails;
selectedLanguages = new HashMap<>();
this.savedLanguageValue = savedLanguageValue;
}
public void setCallback(Callback callback) {
this.callback = callback;
}
@ -51,6 +58,10 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
notifyDataSetChanged();
}
public List<UploadMediaDetail> getItems(){
return uploadMediaDetails;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@ -178,14 +189,14 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
long l) {
description.setSelectedLanguageIndex(position);
String languageCode = ((SpinnerLanguagesAdapter) adapterView.getAdapter())
.getLanguageCode(position);
.getLanguageCode(position);
description.setLanguageCode(languageCode);
selectedLanguages.remove(adapterView);
selectedLanguages.put(adapterView, languageCode);
((SpinnerLanguagesAdapter) adapterView
.getAdapter()).setSelectedLangCode(languageCode);
.getAdapter()).setSelectedLangCode(languageCode);
spinnerDescriptionLanguages.setSelection(position);
Timber.d("Description language code is: "+languageCode);
Timber.d("Description language code is: " + languageCode);
}
@Override
@ -198,8 +209,16 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
if (!TextUtils.isEmpty(savedLanguageValue)) {
// If user has chosen a default language from settings activity
// savedLanguageValue is not null
if(!TextUtils.isEmpty(description.getLanguageCode())) {
spinnerDescriptionLanguages.setSelection(languagesAdapter
.getIndexOfLanguageCode(description.getLanguageCode()));
} else {
spinnerDescriptionLanguages.setSelection(languagesAdapter
.getIndexOfLanguageCode(savedLanguageValue));
}
} else if (!TextUtils.isEmpty(description.getLanguageCode())) {
spinnerDescriptionLanguages.setSelection(languagesAdapter
.getIndexOfLanguageCode(savedLanguageValue));
.getIndexOfLanguageCode(description.getLanguageCode()));
} else {
//Checking whether Language Code attribute is null or not.
if (uploadMediaDetails.get(position).getLanguageCode() != null) {