mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-28 21:33:53 +01:00
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:
parent
e910b1d14f
commit
0269894c64
20 changed files with 855 additions and 14 deletions
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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";
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue