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
This commit is contained in:
Prince kushwaha 2021-06-18 19:00:14 +05:30 committed by GitHub
parent 808f21a1f2
commit b202f553f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 308 additions and 9 deletions

View file

@ -48,4 +48,6 @@ class MediaDataExtractor @Inject constructor(private val mediaClient: MediaClien
)
}
fun getHtmlOfPage(title: String) = mediaClient.getPageHtml(title);
}

View file

@ -0,0 +1,67 @@
package fr.free.nrw.commons.media;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import fr.free.nrw.commons.R;
import java.util.List;
/**
* Adapter for Caption Listview
*/
public class CaptionListViewAdapter extends BaseAdapter {
List<Caption> captions;
public CaptionListViewAdapter(final List<Caption> captions) {
this.captions = captions;
}
/**
* @return size of captions list
*/
@Override
public int getCount() {
return captions.size();
}
/**
* @return Object at position i
*/
@Override
public Object getItem(final int i) {
return null;
}
/**
* @return id for current item
*/
@Override
public long getItemId(final int i) {
return 0;
}
/**
* inflate the view and bind data with UI
*/
@Override
public View getView(final int i, final View view, final ViewGroup viewGroup) {
final TextView captionLanguageTextView;
final TextView captionTextView;
final View captionLayout = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.caption_item, null);
captionLanguageTextView = captionLayout.findViewById(R.id.caption_language_textview);
captionTextView = captionLayout.findViewById(R.id.caption_text);
if (captions.size() == 1 && captions.get(0).getValue().equals("No Caption")) {
captionLanguageTextView.setText(captions.get(i).getLanguage());
captionTextView.setText(captions.get(i).getValue());
} else {
captionLanguageTextView.setText(captions.get(i).getLanguage() + ":");
captionTextView.setText(captions.get(i).getValue());
}
return captionLayout;
}
}

View file

@ -18,16 +18,20 @@ import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.webkit.WebView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.SearchView;
@ -86,6 +90,7 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.lang3.StringUtils;
import org.wikipedia.language.AppLanguageLookUpTable;
import org.wikipedia.util.DateUtil;
import timber.log.Timber;
@ -140,7 +145,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
JsonKvStore applicationKvStore;
private int initialListTop = 0;
@BindView(R.id.description_webview)
WebView descriptionWebView;
@BindView(R.id.mediaDetailFrameLayout)
FrameLayout frameLayout;
@BindView(R.id.mediaDetailImageView)
@ -203,6 +209,19 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
TextView existingCategories;
@BindView(R.id.no_results_found)
TextView noResultsFound;
@BindView(R.id.dummy_caption_description_container)
LinearLayout showCaptionAndDescriptionContainer;
@BindView(R.id.show_caption_description_textview)
TextView showCaptionDescriptionTextView;
@BindView(R.id.caption_listview)
ListView captionsListView;
@BindView(R.id.caption_label)
TextView captionLabel;
@BindView(R.id.description_label)
TextView descriptionLabel;
@BindView(R.id.pb_circular)
ProgressBar progressBar;
String descriptionHtmlCode;
@BindView(R.id.progressBarDeletion)
ProgressBar progressBarDeletion;
@ -302,6 +321,9 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
if(applicationKvStore.getBoolean("login_skipped")){
delete.setVisibility(GONE);
}
handleBackEvent(view);
/**
* Gets the height of the frame layout as soon as the view is ready and updates aspect ratio
* of the picture.
@ -317,14 +339,6 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
return view;
}
@Override
public void onAttach(final Context context) {
super.onAttach(context);
if (getParentFragment() != null) {
callback = (Callback) getParentFragment();
}
}
@OnClick(R.id.mediaDetailImageViewSpacer)
public void launchZoomActivity(View view) {
if (media.getImageUrl() != null) {
@ -769,6 +783,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
}
public void displayHideCategorySearch() {
showCaptionAndDescriptionContainer.setVisibility(GONE);
if (dummyCategoryEditContainer.getVisibility() != VISIBLE) {
dummyCategoryEditContainer.setVisibility(VISIBLE);
} else {
@ -1136,6 +1151,97 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
}
}
@OnClick(R.id.show_caption_description_textview)
void showCaptionAndDescription() {
dummyCategoryEditContainer.setVisibility(GONE);
if (showCaptionAndDescriptionContainer.getVisibility() == GONE) {
showCaptionAndDescriptionContainer.setVisibility(VISIBLE);
setUpCaptionAndDescriptionLayout();
} else {
showCaptionAndDescriptionContainer.setVisibility(GONE);
}
}
/**
* setUp Caption And Description Layout
*/
private void setUpCaptionAndDescriptionLayout() {
List<Caption> captions = getCaptions();
if (descriptionHtmlCode == null) {
progressBar.setVisibility(VISIBLE);
}
getDescription();
CaptionListViewAdapter adapter = new CaptionListViewAdapter(captions);
captionsListView.setAdapter(adapter);
}
/**
* Generate the caption with language
*/
private List<Caption> getCaptions() {
List<Caption> captionList = new ArrayList<>();
Map<String, String> captions = media.getCaptions();
AppLanguageLookUpTable appLanguageLookUpTable = new AppLanguageLookUpTable(getContext());
for (Map.Entry<String, String> map : captions.entrySet()) {
String language = appLanguageLookUpTable.getLocalizedName(map.getKey());
String languageCaption = map.getValue();
captionList.add(new Caption(language, languageCaption));
}
if (captionList.size() == 0) {
captionList.add(new Caption("", "No Caption"));
}
return captionList;
}
private void getDescription() {
compositeDisposable.add(mediaDataExtractor.getHtmlOfPage(media.getFilename())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::extractDescription, Timber::e));
}
/**
* extract the description from html of imagepage
*/
private void extractDescription(String s) {
String descriptionClassName = "<td class=\"description\">";
int start = s.indexOf(descriptionClassName) + descriptionClassName.length();
int end = s.indexOf("</td>", start);
descriptionHtmlCode = "";
for (int i = start; i < end; i++) {
descriptionHtmlCode = descriptionHtmlCode + s.toCharArray()[i];
}
descriptionWebView
.loadDataWithBaseURL(null, descriptionHtmlCode, "text/html", "utf-8", null);
progressBar.setVisibility(GONE);
}
/**
* Handle back event when fragment when showCaptionAndDescriptionContainer is visible
*/
private void handleBackEvent(View view) {
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View view, int keycode, KeyEvent keyEvent) {
if (keycode == KeyEvent.KEYCODE_BACK) {
if (showCaptionAndDescriptionContainer.getVisibility() == VISIBLE) {
showCaptionAndDescriptionContainer.setVisibility(GONE);
return true;
}
}
return false;
}
});
}
public interface Callback {
void nominatingForDeletion(int index);
}

View file

@ -3,6 +3,7 @@ package fr.free.nrw.commons.media;
import io.reactivex.Observable;
import io.reactivex.Single;
import org.wikipedia.wikidata.Entities;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;

View file

@ -3,6 +3,7 @@ package fr.free.nrw.commons.media;
import io.reactivex.Single;
import java.util.Map;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/mainBackground"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/caption_language_textview"
style="@style/CaptionTextLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:text="Caption"
android:textColor="?attr/caption_description_text_color"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="@+id/caption_text"
style="@style/CaptionTextLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:textColor="?attr/caption_description_text_color"
android:textStyle="normal" />
</LinearLayout>
</LinearLayout>

View file

@ -23,6 +23,20 @@
layout="@layout/layout_edit_categories" />
</LinearLayout>
<LinearLayout
android:id="@+id/dummy_caption_description_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:elevation="35dp"
android:orientation="vertical"
android:visibility="gone"
android:weightSum="10">
<include
layout="@layout/show_captions_descriptions" />
</LinearLayout>
<ImageView
android:id="@+id/mediaDetailImageFailed"
android:layout_height="wrap_content"
@ -190,6 +204,15 @@
tools:text="Description of the media goes here. This can potentially be fairly long, and will need to wrap across multiple lines. We hope it looks nice though." />
</LinearLayout>
<TextView
android:id="@+id/show_caption_description_textview"
style="@style/MediaDetailTextLabelGeneric"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen_10"
android:text="@string/media_detail_in_all_languages" />
<View
android:background="?attr/mediaDetailSpacerColor"
android:layout_width="match_parent"

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/dimen_20"
android:background="?attr/mainBackground"
android:elevation="30dp"
android:padding="@dimen/dimen_10">
<TextView
android:id="@+id/caption_label"
style="@style/MediaDetailTextLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Captions"
android:textColor="?attr/caption_description_text_color" />
<ListView
android:id="@+id/caption_listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/caption_label" />
<TextView
android:id="@+id/description_label"
style="@style/MediaDetailTextLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/caption_listview"
android:layout_marginTop="@dimen/dimen_10"
android:text="Descriptions"
android:textColor="?attr/caption_description_text_color" />
<ProgressBar
android:id="@+id/pb_circular"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="?attr/mainBackground"
android:indeterminate="true"
android:indeterminateOnly="true"
android:visibility="gone" />
<WebView
android:id="@+id/description_webview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/description_label"
android:layout_marginTop="@dimen/dimen_10"
android:layout_marginBottom="@dimen/dimen_20"
android:background="?attr/mainBackground"
tools:ignore="WebViewLayout" />
</RelativeLayout>

View file

@ -348,5 +348,6 @@
<string name="leaderboard_used">Benotzt</string>
<string name="limited_connection_mode">Limitéierte Verbindungsmodus</string>
<string name="app_ui_language">Sprooch vum Interface vum Benotzer vun der App</string>
<string name="media_detail_in_all_languages">In all languages</string>
<string name="read_help_link">Liest méi</string>
</resources>

View file

@ -48,6 +48,7 @@
<attr name="contributionsListTextPrimary" format="reference"/>
<attr name="menu_item_tint" format="reference"/>
<attr name="search_icon" format="reference"/>
<attr name="caption_description_text_color" format="reference" />
<declare-styleable name="Badge">
<attr name="boundary" format="color"/>

View file

@ -622,6 +622,7 @@ Upload your first media by tapping on the add button.</string>
<string name="app_ui_language">App user interface language</string>
<string name="remove">Removes a caption and description</string>
<string name="read_help_link">Read more</string>
<string name="media_detail_in_all_languages">In all languages</string>
<string name="choose_a_location">Choose a location</string>
<string name="pan_and_zoom_to_adjust">Pan and zoom to adjust</string>
<string name="exit_location_picker">Exit location picker</string>

View file

@ -19,6 +19,7 @@
<item name="rowButtonColor">@color/button_blue_dark</item>
<item name="reviewHeading">@color/white</item>
<item name="aboutIconsColor">@color/white</item>
<item name="caption_description_text_color">@color/white</item>
<item name="semitransparentText">@color/commons_app_blue_dark</item>
<item name="subBackground">@color/sub_background_dark</item>
@ -76,6 +77,7 @@
<item name="rowButtonColor">@color/button_blue</item>
<item name="reviewHeading">@color/black</item>
<item name="aboutIconsColor">@color/black</item>
<item name="caption_description_text_color">@color/black</item>
<item name="semitransparentText">@color/commons_app_blue_light</item>
<item name="subBackground">@color/sub_background_light</item>
@ -206,6 +208,12 @@
<item name="android:textStyle">bold</item>
</style>
<style name="CaptionTextLabel">
<item name="android:paddingTop">@dimen/dimen_6</item>
<item name="android:paddingLeft">@dimen/tiny_gap</item>
<item name="android:textSize">@dimen/normal_text</item>
</style>
<style name="MediaDetailTextLabelTitle" parent="@style/MediaDetailTextLabel">
<item name="android:textColor">@android:color/white</item>
</style>