Skip to content

Commit 12a83da

Browse files
ashishkumar468Vivek Maskara
authored and
Vivek Maskara
committed
Feature/localised image descriptions (commons-app#1634)
* wip * Changes for adding descriptions in multipe languages[issue commons-app#1501] * Added callback for the adapter * Codacy suggested changes * Sort the languages in the spinner in alphabetical order * scroll view nested scrolling enabled false * Nested scrolling enabled false [Allow rv to expand] * rebased to master, resolved conflicts * replaced setCompoundDrawables with setCompoundDrawablesWithIntrinsicBounds [the former dint used to work on all devices] * replaced setCompoundDrawables with setCompoundDrawablesWithIntrinsicBounds [the former dint used to work on all devices]
1 parent e4c518c commit 12a83da

12 files changed

+622
-122
lines changed

app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import fr.free.nrw.commons.Media;
1414
import fr.free.nrw.commons.settings.Prefs;
1515

16-
public class Contribution extends Media {
16+
public class Contribution extends Media {
1717

1818
public static Creator<Contribution> CREATOR = new Creator<Contribution>() {
1919
@Override

app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
6060
private boolean isCategoryImage;
6161
private MediaDetailPagerFragment.MediaDetailProvider detailProvider;
6262
private int index;
63+
private Locale locale;
6364

6465
public static MediaDetailFragment forMedia(int index, boolean editable, boolean isCategoryImage) {
6566
MediaDetailFragment mf = new MediaDetailFragment();
@@ -198,6 +199,7 @@ public void onGlobalLayout() {
198199
}
199200
};
200201
view.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
202+
locale = getResources().getConfiguration().locale;
201203
return view;
202204
}
203205

@@ -455,7 +457,7 @@ private void updateTheDarkness() {
455457

456458
private String prettyDescription(Media media) {
457459
// @todo use UI language when multilingual descs are available
458-
String desc = media.getDescription("en").trim();
460+
String desc = media.getDescription(locale.getLanguage()).trim();
459461
if (desc.equals("")) {
460462
return getString(R.string.detail_description_empty);
461463
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package fr.free.nrw.commons.upload;
2+
3+
import android.text.TextUtils;
4+
import android.util.TimeUtils;
5+
6+
class Description {
7+
8+
private String languageId;
9+
private String languageDisplayText;
10+
private String descriptionText;
11+
private boolean set;
12+
private int selectedLanguageIndex = -1;
13+
14+
public String getLanguageId() {
15+
return languageId;
16+
}
17+
18+
public void setLanguageId(String languageId) {
19+
this.languageId = languageId;
20+
}
21+
22+
public String getLanguageDisplayText() {
23+
return languageDisplayText;
24+
}
25+
26+
public void setLanguageDisplayText(String languageDisplayText) {
27+
this.languageDisplayText = languageDisplayText;
28+
}
29+
30+
public String getDescriptionText() {
31+
return descriptionText;
32+
}
33+
34+
public void setDescriptionText(String descriptionText) {
35+
this.descriptionText = descriptionText;
36+
37+
if (!TextUtils.isEmpty(descriptionText)) {
38+
set = true;
39+
}
40+
}
41+
42+
public boolean isSet() {
43+
return set;
44+
}
45+
46+
public void setSet(boolean set) {
47+
this.set = set;
48+
}
49+
50+
public int getSelectedLanguageIndex() {
51+
return selectedLanguageIndex;
52+
}
53+
54+
public void setSelectedLanguageIndex(int selectedLanguageIndex) {
55+
this.selectedLanguageIndex = selectedLanguageIndex;
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
package fr.free.nrw.commons.upload;
2+
3+
import static android.view.MotionEvent.ACTION_UP;
4+
5+
import android.content.Context;
6+
import android.graphics.drawable.Drawable;
7+
import android.support.v4.view.ViewCompat;
8+
import android.support.v7.widget.AppCompatSpinner;
9+
import android.support.v7.widget.RecyclerView;
10+
import android.text.Editable;
11+
import android.text.TextUtils;
12+
import android.text.TextWatcher;
13+
import android.view.LayoutInflater;
14+
import android.view.MotionEvent;
15+
import android.view.View;
16+
import android.view.ViewGroup;
17+
import android.widget.AdapterView;
18+
import android.widget.AdapterView.OnItemSelectedListener;
19+
import android.widget.EditText;
20+
import butterknife.BindView;
21+
import butterknife.ButterKnife;
22+
import butterknife.OnTouch;
23+
import fr.free.nrw.commons.R;
24+
import fr.free.nrw.commons.utils.ViewUtil;
25+
import java.util.ArrayList;
26+
import java.util.Collections;
27+
import java.util.Comparator;
28+
import java.util.List;
29+
import java.util.Locale;
30+
31+
class DescriptionsAdapter extends RecyclerView.Adapter<DescriptionsAdapter.ViewHolder> {
32+
33+
List<Description> descriptions;
34+
List<Language> languages;
35+
private Context context;
36+
private Callback callback;
37+
38+
public DescriptionsAdapter() {
39+
descriptions = new ArrayList<>();
40+
descriptions.add(new Description());
41+
languages = new ArrayList<>();
42+
}
43+
44+
public void setCallback(Callback callback) {
45+
this.callback = callback;
46+
}
47+
48+
public void setDescriptions(List<Description> descriptions) {
49+
this.descriptions = descriptions;
50+
notifyDataSetChanged();
51+
}
52+
53+
public void setLanguages(List<Language> languages) {
54+
this.languages = languages;
55+
}
56+
57+
@Override
58+
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
59+
View view = LayoutInflater.from(parent.getContext())
60+
.inflate(R.layout.row_item_description, parent, false);
61+
context = parent.getContext();
62+
ViewHolder viewHolder = new ViewHolder(view);
63+
return viewHolder;
64+
}
65+
66+
@Override
67+
public void onBindViewHolder(ViewHolder holder, int position) {
68+
holder.init(position);
69+
}
70+
71+
@Override
72+
public int getItemCount() {
73+
return descriptions.size();
74+
}
75+
76+
public List<Description> getDescriptions() {
77+
return descriptions;
78+
}
79+
80+
public void addDescription(Description description) {
81+
this.descriptions.add(description);
82+
notifyItemInserted(descriptions.size() - 1);
83+
}
84+
85+
86+
public class ViewHolder extends RecyclerView.ViewHolder {
87+
88+
@BindView(R.id.spinner_description_languages)
89+
AppCompatSpinner spinnerDescriptionLanguages;
90+
@BindView(R.id.et_description_text)
91+
EditText etDescriptionText;
92+
private View view;
93+
94+
95+
public ViewHolder(View itemView) {
96+
super(itemView);
97+
ButterKnife.bind(this, itemView);
98+
this.view = itemView;
99+
}
100+
101+
public void init(int position) {
102+
Description description = descriptions.get(position);
103+
if (!TextUtils.isEmpty(description.getDescriptionText())) {
104+
etDescriptionText.setText(description.getDescriptionText());
105+
} else {
106+
etDescriptionText.setText("");
107+
}
108+
Drawable drawableRight = context.getResources()
109+
.getDrawable(R.drawable.mapbox_info_icon_default);
110+
if (position != 0) {
111+
etDescriptionText.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
112+
} else {
113+
etDescriptionText.setCompoundDrawablesWithIntrinsicBounds(null, null, drawableRight, null);
114+
}
115+
116+
etDescriptionText.addTextChangedListener(new TextWatcher() {
117+
@Override
118+
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
119+
120+
}
121+
122+
@Override
123+
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
124+
125+
}
126+
127+
@Override
128+
public void afterTextChanged(Editable editable) {
129+
description.setDescriptionText(editable.toString());
130+
}
131+
});
132+
133+
etDescriptionText.setOnFocusChangeListener((v, hasFocus) -> {
134+
if (!hasFocus) {
135+
ViewUtil.hideKeyboard(v);
136+
}
137+
});
138+
139+
SpinnerLanguagesAdapter languagesAdapter = new SpinnerLanguagesAdapter(context,
140+
R.layout.row_item_languages_spinner);
141+
Collections.sort(languages, (language, t1) -> language.getLocale().getDisplayLanguage()
142+
.compareTo(t1.getLocale().getDisplayLanguage().toString()));
143+
languagesAdapter.setLanguages(languages);
144+
languagesAdapter.notifyDataSetChanged();
145+
spinnerDescriptionLanguages.setAdapter(languagesAdapter);
146+
147+
if (description.getSelectedLanguageIndex() == -1) {
148+
if (position == 0) {
149+
int defaultLocaleIndex = getIndexOfUserDefaultLocale();
150+
spinnerDescriptionLanguages.setSelection(defaultLocaleIndex);
151+
} else {
152+
spinnerDescriptionLanguages.setSelection(0);
153+
}
154+
} else {
155+
spinnerDescriptionLanguages.setSelection(description.getSelectedLanguageIndex());
156+
}
157+
158+
languages.get(spinnerDescriptionLanguages.getSelectedItemPosition()).setSet(true);
159+
160+
//TODO do it the butterknife way
161+
spinnerDescriptionLanguages.setOnItemSelectedListener(new OnItemSelectedListener() {
162+
@Override
163+
public void onItemSelected(AdapterView<?> adapterView, View view, int position,
164+
long l) {
165+
//TODO handle case when user tries to select an already selected language
166+
updateDescriptionBasedOnSelectedLanguageIndex(description, position);
167+
}
168+
169+
@Override
170+
public void onNothingSelected(AdapterView<?> adapterView) {
171+
172+
}
173+
});
174+
175+
176+
}
177+
178+
@OnTouch(R.id.et_description_text)
179+
boolean descriptionInfo(View view, MotionEvent motionEvent) {
180+
181+
if (getAdapterPosition() == 0) {
182+
//Description info is visible only for the first item
183+
final int value;
184+
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
185+
value = etDescriptionText.getRight() - etDescriptionText
186+
.getCompoundDrawables()[2]
187+
.getBounds().width();
188+
if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() >= value) {
189+
callback.showAlert(R.string.media_detail_description,
190+
R.string.description_info);
191+
return true;
192+
}
193+
} else {
194+
value = etDescriptionText.getLeft() + etDescriptionText
195+
.getCompoundDrawables()[0]
196+
.getBounds().width();
197+
if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() <= value) {
198+
callback.showAlert(R.string.media_detail_description,
199+
R.string.description_info);
200+
return true;
201+
}
202+
}
203+
}
204+
return false;
205+
}
206+
}
207+
208+
private int getIndexOfUserDefaultLocale() {
209+
for (int i = 0; i < languages.size(); i++) {
210+
if (languages.get(i).getLocale()
211+
.equals(context.getResources().getConfiguration().locale)) {
212+
return i;
213+
}
214+
}
215+
return 0;
216+
}
217+
218+
private void updateDescriptionBasedOnSelectedLanguageIndex(Description description,
219+
int position) {
220+
Language language = languages.get(position);
221+
Locale locale = language.getLocale();
222+
description.setSelectedLanguageIndex(position);
223+
description.setLanguageDisplayText(locale.getDisplayName());
224+
description.setLanguageId(locale.getLanguage());
225+
}
226+
227+
public interface Callback {
228+
229+
void showAlert(int mediaDetailDescription, int descriptionInfo);
230+
}
231+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package fr.free.nrw.commons.upload;
2+
3+
import java.util.Locale;
4+
5+
class Language {
6+
7+
private Locale locale;
8+
private boolean isSet = false;
9+
10+
public Language(Locale locale) {
11+
this.locale = locale;
12+
}
13+
14+
public Locale getLocale() {
15+
return locale;
16+
}
17+
18+
public void setLocale(Locale locale) {
19+
this.locale = locale;
20+
}
21+
22+
public boolean isSet() {
23+
return isSet;
24+
}
25+
26+
public void setSet(boolean set) {
27+
isSet = set;
28+
}
29+
}

app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ private void zoomImageFromThumb(final View thumbView, Uri imageuri) {
481481
CurrentAnimator.cancel();
482482
}
483483
isZoom = true;
484-
ViewUtil.hideKeyboard(ShareActivity.this.findViewById(R.id.titleEdit | R.id.descEdit));
484+
ViewUtil.hideKeyboard(ShareActivity.this.findViewById(R.id.titleEdit));
485485
closeFABMenu();
486486
mainFab.setVisibility(View.GONE);
487487

0 commit comments

Comments
 (0)