Send thanks button in more details fragment (#5424)

* Send thanks button in more details fragment

* failing test fix

* suggested fix
This commit is contained in:
Srishti Rohatgi 2024-01-23 19:25:16 +05:30 committed by GitHub
parent 3c1cdf18a1
commit 495d001dc9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 109 additions and 6 deletions

View file

@ -12,7 +12,6 @@ import static fr.free.nrw.commons.description.EditDescriptionConstants.WIKITEXT;
import static fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment.LAST_LOCATION; import static fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment.LAST_LOCATION;
import static fr.free.nrw.commons.utils.LangCodeUtils.getLocalizedResources; import static fr.free.nrw.commons.utils.LangCodeUtils.getLocalizedResources;
import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
@ -23,6 +22,7 @@ import android.graphics.drawable.Animatable;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -64,6 +64,7 @@ import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.MediaDataExtractor; import fr.free.nrw.commons.MediaDataExtractor;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.actions.ThanksClient;
import fr.free.nrw.commons.auth.AccountUtil; import fr.free.nrw.commons.auth.AccountUtil;
import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.category.CategoryClient; import fr.free.nrw.commons.category.CategoryClient;
@ -75,12 +76,15 @@ import fr.free.nrw.commons.delete.DeleteHelper;
import fr.free.nrw.commons.delete.ReasonBuilder; import fr.free.nrw.commons.delete.ReasonBuilder;
import fr.free.nrw.commons.description.DescriptionEditActivity; import fr.free.nrw.commons.description.DescriptionEditActivity;
import fr.free.nrw.commons.description.DescriptionEditHelper; import fr.free.nrw.commons.description.DescriptionEditHelper;
import fr.free.nrw.commons.di.ApplicationlessInjection;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity; import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity;
import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.location.LocationServiceManager; import fr.free.nrw.commons.location.LocationServiceManager;
import fr.free.nrw.commons.media.ZoomableActivity.ZoomableActivityConstants; import fr.free.nrw.commons.media.ZoomableActivity.ZoomableActivityConstants;
import fr.free.nrw.commons.profile.ProfileActivity; import fr.free.nrw.commons.profile.ProfileActivity;
import fr.free.nrw.commons.review.ReviewController;
import fr.free.nrw.commons.review.ReviewHelper;
import fr.free.nrw.commons.settings.Prefs; import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.ui.widget.HtmlTextView; import fr.free.nrw.commons.ui.widget.HtmlTextView;
import fr.free.nrw.commons.upload.categories.UploadCategoriesFragment; import fr.free.nrw.commons.upload.categories.UploadCategoriesFragment;
@ -88,9 +92,13 @@ import fr.free.nrw.commons.upload.depicts.DepictsFragment;
import fr.free.nrw.commons.upload.UploadMediaDetail; import fr.free.nrw.commons.upload.UploadMediaDetail;
import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.DialogUtil;
import fr.free.nrw.commons.utils.PermissionUtils; import fr.free.nrw.commons.utils.PermissionUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import fr.free.nrw.commons.utils.ViewUtilWrapper; import fr.free.nrw.commons.utils.ViewUtilWrapper;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Single; import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -101,11 +109,13 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.wikipedia.dataclient.mwapi.MwQueryPage;
import org.wikipedia.language.AppLanguageLookUpTable; import org.wikipedia.language.AppLanguageLookUpTable;
import org.wikipedia.util.DateUtil; import org.wikipedia.util.DateUtil;
import timber.log.Timber; import timber.log.Timber;
@ -154,6 +164,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
@Inject @Inject
DeleteHelper deleteHelper; DeleteHelper deleteHelper;
@Inject @Inject
ReviewHelper reviewHelper;
@Inject
CategoryEditHelper categoryEditHelper; CategoryEditHelper categoryEditHelper;
@Inject @Inject
CoordinateEditHelper coordinateEditHelper; CoordinateEditHelper coordinateEditHelper;
@ -164,6 +176,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
@Inject @Inject
CategoryClient categoryClient; CategoryClient categoryClient;
@Inject @Inject
ThanksClient thanksClient;
@Inject
@Named("default_preferences") @Named("default_preferences")
JsonKvStore applicationKvStore; JsonKvStore applicationKvStore;
@ -241,6 +255,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
ProgressBar progressBarEditCategory; ProgressBar progressBarEditCategory;
@BindView(R.id.description_edit) @BindView(R.id.description_edit)
Button editDescription; Button editDescription;
@BindView(R.id.sendThanks)
Button sendThanksButton;
private ArrayList<String> categoryNames = new ArrayList<>(); private ArrayList<String> categoryNames = new ArrayList<>();
private String categorySearchQuery; private String categorySearchQuery;
@ -431,6 +447,13 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
enableProgressBar(); enableProgressBar();
} }
if (AccountUtil.getUserName(getContext()) != null && media != null
&& AccountUtil.getUserName(getContext()).equals(media.getAuthor())) {
sendThanksButton.setVisibility(GONE);
} else {
sendThanksButton.setVisibility(VISIBLE);
}
scrollView.getViewTreeObserver().addOnGlobalLayoutListener( scrollView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() { new OnGlobalLayoutListener() {
@Override @Override
@ -780,12 +803,77 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
} }
@OnClick(R.id.copyWikicode) @OnClick(R.id.copyWikicode)
public void onCopyWikicodeClicked(){ public void onCopyWikicodeClicked() {
String data = "[[" + media.getFilename() + "|thumb|" + media.getFallbackDescription() + "]]"; String data =
Utils.copy("wikiCode",data,getContext()); "[[" + media.getFilename() + "|thumb|" + media.getFallbackDescription() + "]]";
Utils.copy("wikiCode", data, getContext());
Timber.d("Generated wikidata copy code: %s", data); Timber.d("Generated wikidata copy code: %s", data);
Toast.makeText(getContext(), getString(R.string.wikicode_copied), Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), getString(R.string.wikicode_copied), Toast.LENGTH_SHORT)
.show();
}
/**
* Sends thanks to author if the author is not the user
*/
@OnClick(R.id.sendThanks)
public void sendThanksToAuthor() {
String fileName = media.getFilename();
if (TextUtils.isEmpty(fileName)) {
Toast.makeText(getContext(), getString(R.string.error_sending_thanks),
Toast.LENGTH_SHORT).show();
return;
}
compositeDisposable.add(reviewHelper.getFirstRevisionOfFile(fileName)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(revision -> sendThanks(getContext(), revision)));
}
/**
* Api call for sending thanks to the author when the author is not the user
* and display toast depending on the result
* @param context context
* @param firstRevision the revision id of the image
*/
@SuppressLint({"CheckResult", "StringFormatInvalid"})
void sendThanks(Context context, MwQueryPage.Revision firstRevision) {
ViewUtil.showShortToast(context,
context.getString(R.string.send_thank_toast, media.getDisplayTitle()));
if (firstRevision == null) {
return;
}
Observable.defer((Callable<ObservableSource<Boolean>>) () -> thanksClient.thank(
firstRevision.getRevisionId()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((result) -> {
displayThanksToast(context, result);
}, Timber::e);
}
/**
* Method to display toast when api call to thank the author is completed
* @param context context
* @param result true if success, false otherwise
*/
@SuppressLint("StringFormatInvalid")
private void displayThanksToast(final Context context, final boolean result) {
final String message;
final String title;
if (result) {
title = context.getString(R.string.send_thank_success_title);
message = context.getString(R.string.send_thank_success_message,
media.getDisplayTitle());
} else {
title = context.getString(R.string.send_thank_failure_title);
message = context.getString(R.string.send_thank_failure_message,
media.getDisplayTitle());
}
ViewUtil.showShortToast(context, message);
} }
@OnClick(R.id.categoryEditButton) @OnClick(R.id.categoryEditButton)

View file

@ -109,7 +109,7 @@ public class ReviewHelper {
* @param filename * @param filename
* @return * @return
*/ */
Observable<MwQueryPage.Revision> getFirstRevisionOfFile(String filename) { public Observable<MwQueryPage.Revision> getFirstRevisionOfFile(String filename) {
return reviewInterface.getFirstRevisionOfFile(filename) return reviewInterface.getFirstRevisionOfFile(filename)
.map(response -> response.query().firstPage().revisions().get(0)); .map(response -> response.query().firstPage().revisions().get(0));
} }

View file

@ -464,6 +464,16 @@
android:text="@string/copy_wikicode" android:text="@string/copy_wikicode"
android:textColor="@color/primaryTextColor" /> android:textColor="@color/primaryTextColor" />
<Button
android:id="@+id/sendThanks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/standard_gap"
android:layout_marginEnd="@dimen/standard_gap"
android:background="@drawable/bg_copy_wikitext_button"
android:text="@string/send_thanks_to_author"
android:textColor="@color/primaryTextColor" />
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -787,6 +787,8 @@ Upload your first media by tapping on the add button.</string>
<string name="learn_how_to_write_a_useful_description">Learn how to write a useful description</string> <string name="learn_how_to_write_a_useful_description">Learn how to write a useful description</string>
<string name="learn_how_to_write_a_useful_caption">Learn how to write a useful caption</string> <string name="learn_how_to_write_a_useful_caption">Learn how to write a useful caption</string>
<string name="see_your_achievements">See your achievements</string> <string name="see_your_achievements">See your achievements</string>
<string name="send_thanks_to_author">Thank the author</string>
<string name="error_sending_thanks">Error sending thanks to author.</string>
<plurals name="custom_picker_images_selected_title_appendix"> <plurals name="custom_picker_images_selected_title_appendix">
<item quantity="one">%d image selected</item> <item quantity="one">%d image selected</item>
<item quantity="other">%d images selected</item> <item quantity="other">%d images selected</item>

View file

@ -316,6 +316,9 @@ class MediaDetailFragmentUnitTests {
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testOnResume() { fun testOnResume() {
Whitebox.setInternalState(fragment, "applicationKvStore", applicationKvStore)
`when`(applicationKvStore.getBoolean("login_skipped")).thenReturn(true)
fragment.onCreateView(layoutInflater, null, savedInstanceState)
fragment.onResume() fragment.onResume()
} }