Fixes previous PR - FIX #2918 Add option for default language for file descriptions (#3020)

* FIX #2918 Add option for default language for file descriptions

* navigation menu error fixed and improvement of code quality

* error language description default fixed

* adapter language selected fixed

* local language selected per default in description language

* Use a better string and variable name as required in review 1

* Add comments

* Add previously missing setValue methods so that list item will be chosen along with the summary

* Add missing Javadocs

* Fix capitalization

* Lint and formatting issues

* Rename methods so it's clearer they are to do with languages

* Use default kv store instead of shared preferences variable

* Make sure saved language code from settings activity is handled on init
This commit is contained in:
neslihanturan 2019-06-24 14:40:12 +03:00 committed by Josephine Lim
parent 2837748540
commit dd50e83319
8 changed files with 150 additions and 29 deletions

View file

@ -8,6 +8,7 @@ public class Prefs {
public static final String UPLOADS_SHOWING = "uploadsshowing";
public static final String IS_CONTRIBUTION_COUNT_CHANGED = "ccontributionCountChanged";
public static final String MANAGED_EXIF_TAGS = "managedExifTags";
public static final String KEY_LANGUAGE_VALUE = "languageDescription";
public static class Licenses {
public static final String CC_BY_SA_3 = "CC BY-SA 3.0";

View file

@ -1,12 +1,15 @@
package fr.free.nrw.commons.settings;
import android.Manifest;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.MultiSelectListPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.SwitchPreference;
import android.text.Editable;
import android.text.TextWatcher;
@ -15,10 +18,10 @@ import com.karumi.dexter.Dexter;
import com.karumi.dexter.listener.PermissionGrantedResponse;
import com.karumi.dexter.listener.single.BasePermissionListener;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.inject.Inject;
import javax.inject.Named;
@ -30,6 +33,7 @@ import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.logging.CommonsLogSender;
import fr.free.nrw.commons.utils.PermissionUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import fr.free.nrw.commons.upload.Language;
public class SettingsFragment extends PreferenceFragment {
@ -38,6 +42,7 @@ public class SettingsFragment extends PreferenceFragment {
JsonKvStore defaultKvStore;
@Inject
CommonsLogSender commonsLogSender;
private ListPreference listPreference;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -108,6 +113,8 @@ public class SettingsFragment extends PreferenceFragment {
}
});
listPreference = (ListPreference) findPreference("descriptionDefaultLanguagePref");
prepareLanguages();
Preference betaTesterPreference = findPreference("becomeBetaTester");
betaTesterPreference.setOnPreferenceClickListener(preference -> {
Utils.handleWebUrl(getActivity(), Uri.parse(getResources().getString(R.string.beta_opt_in_link)));
@ -133,6 +140,74 @@ public class SettingsFragment extends PreferenceFragment {
}
}
/**
* Prepares language summary and language codes list and adds them to list preference as pairs.
* Uses previously saved language if there is any, if not uses phone local as initial language.
* Adds preference changed listener and saves value choosen by user to shared preferences
* to remember later
*/
private void prepareLanguages() {
List<String> languageNamesList = new ArrayList<>();
List<String> languageCodesList = new ArrayList<>();
List<Language> languages = getLanguagesSupportedByDevice();
for(Language language: languages) {
// Go through all languages and add them to lists
if(!languageCodesList.contains(language.getLocale().getLanguage())) {
// This if prevents us from adding same language twice
languageNamesList.add(language.getLocale().getDisplayName());
languageCodesList.add(language.getLocale().getLanguage());
}
}
CharSequence[] languageNames = languageNamesList.toArray(new CharSequence[0]);
CharSequence[] languageCodes = languageCodesList.toArray(new CharSequence[0]);
// Add all languages and languages codes to lists preference as pair
listPreference.setEntries(languageNames);
listPreference.setEntryValues(languageCodes);
// Gets current language code from shared preferences
String languageCode = getCurrentLanguageCode();
if(languageCode.equals("")){
// If current language code is empty, means none selected by user yet so use phone local
listPreference.setSummary(Locale.getDefault().getDisplayLanguage());
listPreference.setValue(Locale.getDefault().getLanguage());
} else {
// If any language is selected by user previously, use it
int prefIndex = listPreference.findIndexOfValue(languageCode);
listPreference.setSummary(listPreference.getEntries()[prefIndex]);
listPreference.setValue(languageCode);
}
listPreference.setOnPreferenceChangeListener((preference, newValue) -> {
String userSelectedValue = (String) newValue;
int prefIndex = listPreference.findIndexOfValue(userSelectedValue);
listPreference.setSummary(listPreference.getEntries()[prefIndex]);
saveLanguageValue(userSelectedValue);
return true;
});
}
private void saveLanguageValue(String userSelectedValue) {
defaultKvStore.putString(Prefs.KEY_LANGUAGE_VALUE, userSelectedValue);
}
private String getCurrentLanguageCode() {
return defaultKvStore.getString(Prefs.KEY_LANGUAGE_VALUE, "");
}
private List<Language> getLanguagesSupportedByDevice() {
List<Language> languages = new ArrayList<>();
Locale[] localesArray = Locale.getAvailableLocales();
for (Locale locale : localesArray) {
languages.add(new Language(locale));
}
Collections.sort(languages, (language, t1) -> language.getLocale().getDisplayName()
.compareTo(t1.getLocale().getDisplayName()));
return languages;
}
/**
* First checks for external storage permissions and then sends logs via email
*/

View file

@ -32,10 +32,12 @@ public class DescriptionsAdapter extends RecyclerView.Adapter<DescriptionsAdapte
private Callback callback;
private BiMap<AdapterView, String> selectedLanguages;
private String savedLanguageValue;
public DescriptionsAdapter() {
public DescriptionsAdapter(String savedLanguageValue) {
descriptions = new ArrayList<>();
selectedLanguages = new BiMap<>();
this.savedLanguageValue = savedLanguageValue;
}
public void setCallback(Callback callback) {
@ -143,14 +145,15 @@ public class DescriptionsAdapter extends RecyclerView.Adapter<DescriptionsAdapte
private void initLanguageSpinner(int position, Description description) {
SpinnerLanguagesAdapter languagesAdapter = new SpinnerLanguagesAdapter(
spinnerDescriptionLanguages.getContext(),
R.layout.row_item_languages_spinner, selectedLanguages);
R.layout.row_item_languages_spinner, selectedLanguages,
savedLanguageValue);
languagesAdapter.notifyDataSetChanged();
spinnerDescriptionLanguages.setAdapter(languagesAdapter);
spinnerDescriptionLanguages.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position,
long l) {
long l) {
description.setSelectedLanguageIndex(position);
String languageCode = ((SpinnerLanguagesAdapter) adapterView.getAdapter())
.getLanguageCode(position);
@ -159,22 +162,28 @@ public class DescriptionsAdapter extends RecyclerView.Adapter<DescriptionsAdapte
selectedLanguages.put(adapterView, languageCode);
((SpinnerLanguagesAdapter) adapterView
.getAdapter()).selectedLangCode = languageCode;
Timber.d("Description language code is: "+languageCode);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
if (description.getSelectedLanguageIndex() == -1) {
if (position == 0) {
int defaultLocaleIndex = languagesAdapter
.getIndexOfUserDefaultLocale(spinnerDescriptionLanguages.getContext());
spinnerDescriptionLanguages.setSelection(defaultLocaleIndex, true);
if (savedLanguageValue != null) {
// If user has chosen a default language from settings activity savedLanguageValue is not null
spinnerDescriptionLanguages.setSelection(languagesAdapter.getIndexOfLanguageCode(savedLanguageValue));
} else {
spinnerDescriptionLanguages.setSelection(0);
if (position == 0) {
int defaultLocaleIndex = languagesAdapter
.getIndexOfUserDefaultLocale(spinnerDescriptionLanguages.getContext());
spinnerDescriptionLanguages.setSelection(defaultLocaleIndex, true);
} else {
spinnerDescriptionLanguages.setSelection(0);
}
}
} else {
spinnerDescriptionLanguages.setSelection(description.getSelectedLanguageIndex());
selectedLanguages.put(spinnerDescriptionLanguages, description.getLanguageCode());

View file

@ -2,7 +2,7 @@ package fr.free.nrw.commons.upload;
import java.util.Locale;
class Language {
public class Language {
private Locale locale;
private boolean isSet = false;

View file

@ -1,7 +1,9 @@
package fr.free.nrw.commons.upload;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -16,15 +18,16 @@ import java.util.Locale;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.utils.BiMap;
import fr.free.nrw.commons.utils.LangCodeUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
public class SpinnerLanguagesAdapter extends ArrayAdapter {
@ -34,11 +37,16 @@ public class SpinnerLanguagesAdapter extends ArrayAdapter {
private List<String> languageCodesList;
private final BiMap<AdapterView, String> selectedLanguages;
public String selectedLangCode="";
private Context context;
private boolean dropDownClicked;
private String savedLanguageValue;
public SpinnerLanguagesAdapter(@NonNull Context context,
int resource, BiMap<AdapterView, String> selectedLanguages) {
int resource,
BiMap<AdapterView, String> selectedLanguages,
String savedLanguageValue) {
super(context, resource);
this.resource = resource;
this.layoutInflater = LayoutInflater.from(context);
@ -46,6 +54,9 @@ public class SpinnerLanguagesAdapter extends ArrayAdapter {
languageCodesList = new ArrayList<>();
prepareLanguages();
this.selectedLanguages = selectedLanguages;
this.context = context;
this.dropDownClicked = false;
this.savedLanguageValue = savedLanguageValue;
}
private void prepareLanguages() {
@ -90,7 +101,9 @@ public class SpinnerLanguagesAdapter extends ArrayAdapter {
convertView = layoutInflater.inflate(resource, parent, false);
}
ViewHolder holder = new ViewHolder(convertView);
holder.init(position, true);
holder.init(position, true, savedLanguageValue);
dropDownClicked = true;
return convertView;
}
@ -105,7 +118,7 @@ public class SpinnerLanguagesAdapter extends ArrayAdapter {
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.init(position, false);
holder.init(position, false, savedLanguageValue);
return convertView;
}
@ -122,17 +135,23 @@ public class SpinnerLanguagesAdapter extends ArrayAdapter {
ButterKnife.bind(this, itemView);
}
public void init(int position, boolean isDropDownView) {
final String languageCode = LangCodeUtils.fixLanguageCode(languageCodesList.get(position));
final String languageName = String.format("%s%s", languageNamesList.get(position)
.substring(0, 1).toUpperCase(), languageNamesList.get(position).substring(1));
public void init(int position, boolean isDropDownView, String savedLanguageValue) {
String languageCode = LangCodeUtils.fixLanguageCode(languageCodesList.get(position));
final String languageName = StringUtils.capitalize(languageNamesList.get(position));
if(savedLanguageValue.equals("")){
savedLanguageValue = Locale.getDefault().getLanguage();
}
if (!isDropDownView) {
if( !dropDownClicked){
languageCode = LangCodeUtils.fixLanguageCode(savedLanguageValue);
}
view.setVisibility(View.GONE);
if(languageCode.length()>2)
tvLanguage.setText(languageCode.subSequence(0,2));
if (languageCode.length() > 2)
tvLanguage.setText(languageCode.substring(0, 2));
else
tvLanguage.setText(languageCode);
} else {
view.setVisibility(View.VISIBLE);
if (languageCodesList.get(position).isEmpty()) {
@ -141,7 +160,7 @@ public class SpinnerLanguagesAdapter extends ArrayAdapter {
} else {
tvLanguage.setText(
String.format("%s [%s]", languageName, languageCode));
if(selectedLanguages.containsKey(languageCodesList.get(position))&&
if (selectedLanguages.containsKey(languageCodesList.get(position)) &&
!languageCodesList.get(position).equals(selectedLangCode)) {
tvLanguage.setTextColor(Color.GRAY);
}
@ -158,4 +177,7 @@ public class SpinnerLanguagesAdapter extends ArrayAdapter {
return languageCodesList.indexOf(context.getResources().getConfiguration().locale.getLanguage());
}
int getIndexOfLanguageCode(String languageCode) {
return languageCodesList.indexOf(languageCode);
}
}

View file

@ -32,6 +32,7 @@ import java.util.List;
import java.util.Locale;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.BindView;
import butterknife.ButterKnife;
@ -39,8 +40,10 @@ import butterknife.OnClick;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.filepicker.UploadableFile;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.upload.Description;
import fr.free.nrw.commons.upload.DescriptionsAdapter;
import fr.free.nrw.commons.upload.SimilarImageDialogFragment;
@ -86,6 +89,11 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
@Inject
UploadMediaDetailsContract.UserActionListener presenter;
@Inject
@Named("default_preferences")
JsonKvStore defaultKvStore;
private UploadableFile uploadableFile;
private String source;
private Place place;
@ -214,7 +222,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
* init the recycler veiw
*/
private void initRecyclerView() {
descriptionsAdapter = new DescriptionsAdapter();
descriptionsAdapter = new DescriptionsAdapter(defaultKvStore.getString(Prefs.KEY_LANGUAGE_VALUE,""));
descriptionsAdapter.setCallback(this::showInfoAlert);
rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext()));
rvDescriptions.setAdapter(descriptionsAdapter);

View file

@ -558,4 +558,5 @@ Upload your first media by tapping on the add button.</string>
<string name="upload_cancelled">Cancelled Upload</string>
<string name="previous_image_title_description_not_found">There is no data for previous image\'s title or description</string>
<string name="dialog_box_text_nomination">Why should %1$s be deleted?</string>
<string name="default_description_language">Default description language</string>
</resources>

View file

@ -29,6 +29,11 @@
android:inputType="number"
android:maxLength="3" />
<fr.free.nrw.commons.ui.LongTitlePreferences.LongTitleListPreference
android:key="descriptionDefaultLanguagePref"
android:title= "@string/default_description_language"
android:summary="English" />
<fr.free.nrw.commons.ui.LongTitlePreferences.LongTitleSwitchPreference
android:key="useAuthorName"
android:title="@string/preference_author_name_toggle"