Skip to content

Fix 4615: Option for editing caption and description #4672

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3d22463
DescriptionEditHelper implemented
Ayan-10 Sep 29, 2021
b4ce92e
Description extracted
Ayan-10 Oct 7, 2021
8937945
Description editable
Ayan-10 Oct 13, 2021
82c3c2d
No description condition handled
Ayan-10 Oct 13, 2021
db80d78
Code cleanup
Ayan-10 Oct 13, 2021
b91f124
Added javadocs
Ayan-10 Oct 13, 2021
34c33c0
toolbar added
Ayan-10 Oct 13, 2021
380f319
Merge branch 'master' into 4615_edit_description
Ayan-10 Oct 16, 2021
8cf47f8
Merge branch 'master' of https://github.com/Ayan-10/apps-android-comm…
Ayan-10 Oct 16, 2021
fb1e76a
Merge remote-tracking branch 'origin/4615_edit_description' into 4615…
Ayan-10 Oct 16, 2021
a50483b
API call done
Ayan-10 Oct 17, 2021
2a553f0
Caption edit available
Ayan-10 Oct 19, 2021
81c76ab
Progress dialog added
Ayan-10 Oct 20, 2021
f46d6de
Log
Ayan-10 Oct 20, 2021
6060087
Problem with ButterKnife
Ayan-10 Oct 20, 2021
1e766fd
Caption is editable
Ayan-10 Oct 21, 2021
d4ca4c8
Merge branch 'commons-app:master' into 4615_edit_description
Ayan-10 Oct 21, 2021
3402910
Merge branch '4615_edit_description' of https://github.com/Ayan-10/ap…
Ayan-10 Oct 21, 2021
5d44523
Removed unused import
Ayan-10 Oct 21, 2021
92f98bd
Merge branch '4615_edit_captions' into 4615_edit_description
Ayan-10 Oct 21, 2021
7339a80
Merge branch 'master' of https://github.com/Ayan-10/apps-android-comm…
Ayan-10 Oct 23, 2021
2388dfe
Manifest file reverted
Ayan-10 Oct 23, 2021
19f2873
Manifest file reverted
Ayan-10 Oct 23, 2021
ac21978
Manifest file reverted
Ayan-10 Oct 23, 2021
9cd0196
View binding added
Ayan-10 Oct 26, 2021
074268e
Post operation test added
Ayan-10 Oct 26, 2021
9760462
Merge branch 'commons-app:master' into 4615_edit_description
Ayan-10 Oct 26, 2021
6fcf3fd
Java docs added
Ayan-10 Oct 30, 2021
4cf1ea4
Java docs added
Ayan-10 Oct 30, 2021
f77f522
Merge branch 'commons-app:master' into 4615_edit_description
Ayan-10 Oct 30, 2021
85fb007
MediaDetailFragment unit tests added
Ayan-10 Oct 31, 2021
2a38826
Test added
Ayan-10 Nov 8, 2021
ea1e81d
Merge branch 'commons-app:master' into 4615_edit_description
Ayan-10 Nov 11, 2021
a60f8c1
Merge branch 'commons-app:master' into 4615_edit_description
Ayan-10 Nov 27, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
android:requestLegacyExternalStorage = "true"
tools:ignore="GoogleAppIndexingWarning">

<activity
android:name=".description.DescriptionEditActivity"
android:exported="true" />

<activity android:name="org.acra.dialog.CrashReportDialog"
android:process=":acra"
android:launchMode="singleInstance"
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
18 changes: 18 additions & 0 deletions app/src/main/java/fr/free/nrw/commons/actions/PageEditClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/fr/free/nrw/commons/actions/PageEditInterface.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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.*

/**
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Loading