mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
* initial changes * add search feature for selecting language * add search feature for selecting language * upload issue fix * minor improvement * added test and updated settings language selection ui Co-authored-by: Pratham2305 <Pratham2305@users.noreply.github.com>
This commit is contained in:
parent
fcb7ccae3c
commit
06a347eee1
9 changed files with 524 additions and 207 deletions
|
|
@ -4,17 +4,24 @@ import static android.content.Context.MODE_PRIVATE;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.Dialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ListView;
|
||||||
import androidx.preference.ListPreference;
|
import androidx.preference.ListPreference;
|
||||||
import androidx.preference.MultiSelectListPreference;
|
import androidx.preference.MultiSelectListPreference;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.Preference.OnPreferenceChangeListener;
|
import androidx.preference.Preference.OnPreferenceClickListener;
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
import androidx.preference.PreferenceGroupAdapter;
|
import androidx.preference.PreferenceGroupAdapter;
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
@ -32,16 +39,17 @@ import fr.free.nrw.commons.contributions.MainActivity;
|
||||||
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
||||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||||
import fr.free.nrw.commons.logging.CommonsLogSender;
|
import fr.free.nrw.commons.logging.CommonsLogSender;
|
||||||
|
import fr.free.nrw.commons.upload.LanguagesAdapter;
|
||||||
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.ViewUtil;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import org.wikipedia.language.AppLanguageLookUpTable;
|
|
||||||
|
|
||||||
public class SettingsFragment extends PreferenceFragmentCompat {
|
public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
|
|
||||||
|
|
@ -53,8 +61,8 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
CommonsLogSender commonsLogSender;
|
CommonsLogSender commonsLogSender;
|
||||||
|
|
||||||
private ListPreference themeListPreference;
|
private ListPreference themeListPreference;
|
||||||
private ListPreference descriptionLanguageListPreference;
|
private Preference descriptionLanguageListPreference;
|
||||||
private ListPreference appUiLanguageListPreference;
|
private Preference appUiLanguageListPreference;
|
||||||
private String keyLanguageListPreference;
|
private String keyLanguageListPreference;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -80,15 +88,50 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets current language code from shared preferences
|
||||||
|
String languageCode;
|
||||||
|
|
||||||
appUiLanguageListPreference = findPreference("appUiDefaultLanguagePref");
|
appUiLanguageListPreference = findPreference("appUiDefaultLanguagePref");
|
||||||
assert appUiLanguageListPreference != null;
|
assert appUiLanguageListPreference != null;
|
||||||
keyLanguageListPreference = appUiLanguageListPreference.getKey();
|
keyLanguageListPreference = appUiLanguageListPreference.getKey();
|
||||||
prepareAppLanguages(keyLanguageListPreference);
|
languageCode = getCurrentLanguageCode(keyLanguageListPreference);
|
||||||
|
assert languageCode != null;
|
||||||
|
if (languageCode.equals("")) {
|
||||||
|
// If current language code is empty, means none selected by user yet so use phone local
|
||||||
|
appUiLanguageListPreference.setSummary(Locale.getDefault().getDisplayLanguage());
|
||||||
|
} else {
|
||||||
|
// If any language is selected by user previously, use it
|
||||||
|
Locale defLocale = new Locale(languageCode);
|
||||||
|
appUiLanguageListPreference.setSummary((defLocale).getDisplayLanguage(defLocale));
|
||||||
|
}
|
||||||
|
appUiLanguageListPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
prepareAppLanguages(appUiLanguageListPreference.getKey());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
descriptionLanguageListPreference = findPreference("descriptionDefaultLanguagePref");
|
descriptionLanguageListPreference = findPreference("descriptionDefaultLanguagePref");
|
||||||
assert descriptionLanguageListPreference != null;
|
assert descriptionLanguageListPreference != null;
|
||||||
keyLanguageListPreference = descriptionLanguageListPreference.getKey();
|
keyLanguageListPreference = descriptionLanguageListPreference.getKey();
|
||||||
prepareAppLanguages(keyLanguageListPreference);
|
languageCode = getCurrentLanguageCode(keyLanguageListPreference);
|
||||||
|
assert languageCode != null;
|
||||||
|
if (languageCode.equals("")) {
|
||||||
|
// If current language code is empty, means none selected by user yet so use phone local
|
||||||
|
descriptionLanguageListPreference.setSummary(Locale.getDefault().getDisplayLanguage());
|
||||||
|
} else {
|
||||||
|
// If any language is selected by user previously, use it
|
||||||
|
Locale defLocale = new Locale(languageCode);
|
||||||
|
descriptionLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
|
||||||
|
}
|
||||||
|
descriptionLanguageListPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
prepareAppLanguages(descriptionLanguageListPreference.getKey());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Preference betaTesterPreference = findPreference("becomeBetaTester");
|
Preference betaTesterPreference = findPreference("becomeBetaTester");
|
||||||
betaTesterPreference.setOnPreferenceClickListener(preference -> {
|
betaTesterPreference.setOnPreferenceClickListener(preference -> {
|
||||||
|
|
@ -156,75 +199,98 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares language summary and language codes list and adds them to list preference as pairs.
|
* Prepare and Show language selection dialog box
|
||||||
* Uses previously saved language if there is any, if not uses phone locale as initial language.
|
* Uses previously saved language if there is any, if not uses phone locale as initial language.
|
||||||
|
* Disable default/already selected language from dialog box
|
||||||
* Get ListPreference key and act accordingly for each ListPreference.
|
* Get ListPreference key and act accordingly for each ListPreference.
|
||||||
* Adds preference changed listener and saves value chosen by user to shared preferences
|
* saves value chosen by user to shared preferences
|
||||||
* to remember later and recall MainActivity to reflect language changes
|
* to remember later and recall MainActivity to reflect language changes
|
||||||
* @param keyListPreference
|
* @param keyListPreference
|
||||||
*/
|
*/
|
||||||
private void prepareAppLanguages(final String keyListPreference) {
|
private void prepareAppLanguages(final String keyListPreference) {
|
||||||
final List<String> languageNamesList;
|
|
||||||
final List<String> languageCodesList;
|
|
||||||
final AppLanguageLookUpTable appLanguageLookUpTable = new AppLanguageLookUpTable(
|
|
||||||
Objects.requireNonNull(getContext()));
|
|
||||||
languageNamesList = appLanguageLookUpTable.getLocalizedNames();
|
|
||||||
languageCodesList = appLanguageLookUpTable.getCodes();
|
|
||||||
List<String> languageNameWithCodeList = new ArrayList<>();
|
|
||||||
|
|
||||||
for (int i = 0; i < languageNamesList.size(); i++) {
|
|
||||||
languageNameWithCodeList.add(languageNamesList.get(i) + "[" + languageCodesList.get(i) + "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
final CharSequence[] languageNames = languageNamesList.toArray(new CharSequence[0]);
|
|
||||||
final CharSequence[] languageCodes = languageCodesList.toArray(new CharSequence[0]);
|
|
||||||
// Add all languages and languages codes to lists preference as pair
|
|
||||||
|
|
||||||
// Gets current language code from shared preferences
|
// Gets current language code from shared preferences
|
||||||
final String languageCode = getCurrentLanguageCode(keyListPreference);
|
final String languageCode = getCurrentLanguageCode(keyListPreference);
|
||||||
|
HashMap<Integer, String> selectedLanguages = new HashMap<>();
|
||||||
|
|
||||||
if (keyListPreference.equals("appUiDefaultLanguagePref")) {
|
if (keyListPreference.equals("appUiDefaultLanguagePref")) {
|
||||||
appUiLanguageListPreference.setEntries(languageNames);
|
|
||||||
appUiLanguageListPreference.setEntryValues(languageCodes);
|
|
||||||
|
|
||||||
assert languageCode != null;
|
assert languageCode != null;
|
||||||
if (languageCode.equals("")) {
|
if (languageCode.equals("")) {
|
||||||
// If current language code is empty, means none selected by user yet so use phone local
|
selectedLanguages.put(0, Locale.getDefault().getLanguage());
|
||||||
appUiLanguageListPreference.setValue(Locale.getDefault().getLanguage());
|
|
||||||
} else {
|
} else {
|
||||||
// If any language is selected by user previously, use it
|
selectedLanguages.put(0, languageCode);
|
||||||
appUiLanguageListPreference.setValue(languageCode);
|
}
|
||||||
|
} else if (keyListPreference.equals("descriptionDefaultLanguagePref")) {
|
||||||
|
|
||||||
|
assert languageCode != null;
|
||||||
|
if (languageCode.equals("")) {
|
||||||
|
selectedLanguages.put(0, Locale.getDefault().getLanguage());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
selectedLanguages.put(0, languageCode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appUiLanguageListPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
LanguagesAdapter languagesAdapter = new LanguagesAdapter(
|
||||||
final String userSelectedValue = (String) newValue;
|
getActivity(),
|
||||||
setLocale(Objects.requireNonNull(getActivity()), userSelectedValue);
|
selectedLanguages
|
||||||
saveLanguageValue(userSelectedValue, keyListPreference);
|
);
|
||||||
|
|
||||||
|
Dialog dialog = new Dialog(getActivity());
|
||||||
|
dialog.setContentView(R.layout.dialog_select_language);
|
||||||
|
dialog.setCanceledOnTouchOutside(true);
|
||||||
|
dialog.getWindow().setLayout((int)(getActivity().getResources().getDisplayMetrics().widthPixels*0.90),
|
||||||
|
(int)(getActivity().getResources().getDisplayMetrics().heightPixels*0.90));
|
||||||
|
dialog.show();
|
||||||
|
|
||||||
|
EditText editText = dialog.findViewById(R.id.search_language);
|
||||||
|
ListView listView = dialog.findViewById(R.id.language_list);
|
||||||
|
|
||||||
|
listView.setAdapter(languagesAdapter);
|
||||||
|
|
||||||
|
editText.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
|
||||||
|
int i2) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence charSequence, int i, int i1,
|
||||||
|
int i2) {
|
||||||
|
languagesAdapter.getFilter().filter(charSequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable editable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
listView.setOnItemClickListener(new OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> adapterView, View view, int i,
|
||||||
|
long l) {
|
||||||
|
String languageCode = ((LanguagesAdapter) adapterView.getAdapter())
|
||||||
|
.getLanguageCode(i);
|
||||||
|
saveLanguageValue(languageCode, keyListPreference);
|
||||||
|
Locale defLocale = new Locale(languageCode);
|
||||||
|
if(keyListPreference.equals("appUiDefaultLanguagePref")) {
|
||||||
|
appUiLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
|
||||||
|
setLocale(Objects.requireNonNull(getActivity()), languageCode);
|
||||||
getActivity().recreate();
|
getActivity().recreate();
|
||||||
final Intent intent = new Intent(getActivity(), MainActivity.class);
|
final Intent intent = new Intent(getActivity(), MainActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (keyListPreference.equals("descriptionDefaultLanguagePref")) {
|
|
||||||
descriptionLanguageListPreference.setEntries(languageNames);
|
|
||||||
descriptionLanguageListPreference.setEntryValues(languageCodes);
|
|
||||||
|
|
||||||
assert languageCode != null;
|
|
||||||
if (languageCode.equals("")) {
|
|
||||||
// If current language code is empty, means none selected by user yet so use phone local
|
|
||||||
descriptionLanguageListPreference.setValue(Locale.getDefault().getLanguage());
|
|
||||||
}else {
|
}else {
|
||||||
// If any language is selected by user previously, use it
|
descriptionLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale));
|
||||||
descriptionLanguageListPreference.setValue(languageCode);
|
}
|
||||||
|
dialog.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptionLanguageListPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
|
||||||
final String userSelectedValue = (String) newValue;
|
|
||||||
saveLanguageValue(userSelectedValue, keyListPreference);
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
dialog.setOnDismissListener(
|
||||||
|
dialogInterface -> languagesAdapter.getFilter().filter(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
131
app/src/main/java/fr/free/nrw/commons/upload/LanguagesAdapter.kt
Normal file
131
app/src/main/java/fr/free/nrw/commons/upload/LanguagesAdapter.kt
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
package fr.free.nrw.commons.upload
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.Filter
|
||||||
|
import androidx.core.os.ConfigurationCompat
|
||||||
|
import fr.free.nrw.commons.R
|
||||||
|
import fr.free.nrw.commons.utils.LangCodeUtils
|
||||||
|
import kotlinx.android.synthetic.main.row_item_languages_spinner.view.*
|
||||||
|
import org.apache.commons.lang3.StringUtils
|
||||||
|
import org.wikipedia.language.AppLanguageLookUpTable
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.LinkedHashMap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class handles the display of language dialog and their views for UploadMediaDetailFragment
|
||||||
|
*
|
||||||
|
* @property selectedLanguages - controls the enabled state of item views
|
||||||
|
*
|
||||||
|
* @param context - required by super constructor
|
||||||
|
*/
|
||||||
|
class LanguagesAdapter constructor(
|
||||||
|
context: Context,
|
||||||
|
private val selectedLanguages: HashMap<*, String>
|
||||||
|
) : ArrayAdapter<String?>(context, R.layout.row_item_languages_spinner) {
|
||||||
|
|
||||||
|
private var languageNamesList: List<String>
|
||||||
|
private var languageCodesList: List<String>
|
||||||
|
|
||||||
|
var language: AppLanguageLookUpTable = AppLanguageLookUpTable(context)
|
||||||
|
init {
|
||||||
|
languageNamesList = language.localizedNames
|
||||||
|
languageCodesList = language.codes
|
||||||
|
}
|
||||||
|
|
||||||
|
private val filter = LanguageFilter()
|
||||||
|
var selectedLangCode = ""
|
||||||
|
|
||||||
|
override fun isEnabled(position: Int) = languageCodesList[position].let {
|
||||||
|
it.isNotEmpty() && !selectedLanguages.containsValue(it) && it != selectedLangCode
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCount() = languageNamesList.size
|
||||||
|
|
||||||
|
|
||||||
|
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||||
|
var rowView: View
|
||||||
|
if(convertView != null) {
|
||||||
|
rowView = convertView
|
||||||
|
}else {
|
||||||
|
rowView = LayoutInflater.from(context).inflate(R.layout.row_item_languages_spinner, parent, false)
|
||||||
|
}
|
||||||
|
val languageCode = languageCodesList[position]
|
||||||
|
val languageName = languageNamesList[position]
|
||||||
|
rowView.tv_language.let {
|
||||||
|
it.isEnabled = isEnabled(position)
|
||||||
|
if (languageCode.isEmpty()) {
|
||||||
|
it.text = StringUtils.capitalize(languageName)
|
||||||
|
it.textAlignment = View.TEXT_ALIGNMENT_CENTER
|
||||||
|
} else {
|
||||||
|
it.text =
|
||||||
|
"${StringUtils.capitalize(languageName)}" +
|
||||||
|
" [${LangCodeUtils.fixLanguageCode(languageCode)}]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rowView
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLanguageCode(position: Int): String {
|
||||||
|
return languageCodesList[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getIndexOfUserDefaultLocale(context: Context): Int {
|
||||||
|
return language.codes.indexOf(context.locale.language)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getIndexOfLanguageCode(languageCode: String): Int {
|
||||||
|
return languageCodesList.indexOf(languageCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun getFilter() = filter
|
||||||
|
|
||||||
|
inner class LanguageFilter : Filter() {
|
||||||
|
|
||||||
|
override fun performFiltering(constraint: CharSequence?): FilterResults {
|
||||||
|
val filterResults = FilterResults()
|
||||||
|
val temp: LinkedHashMap<String, String> = LinkedHashMap()
|
||||||
|
if (constraint != null && language.localizedNames != null) {
|
||||||
|
val length: Int = language.localizedNames.size
|
||||||
|
var i = 0
|
||||||
|
while (i < length) {
|
||||||
|
val key: String = language.codes[i]
|
||||||
|
val value: String = language.localizedNames[i]
|
||||||
|
val defaultlanguagecode = getIndexOfUserDefaultLocale(context)
|
||||||
|
if(value.contains(constraint, true) || Locale(key).getDisplayName(
|
||||||
|
Locale(language.codes[defaultlanguagecode])).contains(constraint, true))
|
||||||
|
temp[key] = value
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
filterResults.values = temp
|
||||||
|
filterResults.count = temp.size
|
||||||
|
}
|
||||||
|
return filterResults
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun publishResults(constraint: CharSequence?, results: FilterResults) {
|
||||||
|
if (results.count > 0) {
|
||||||
|
languageCodesList =
|
||||||
|
ArrayList((results.values as LinkedHashMap<String, String>).keys)
|
||||||
|
languageNamesList =
|
||||||
|
ArrayList((results.values as LinkedHashMap<String, String>).values)
|
||||||
|
notifyDataSetChanged()
|
||||||
|
} else {
|
||||||
|
languageCodesList = ArrayList()
|
||||||
|
languageNamesList = ArrayList()
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private val Context.locale: Locale
|
||||||
|
get() = ConfigurationCompat.getLocales(resources.configuration)[0]
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
package fr.free.nrw.commons.upload
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.ArrayAdapter
|
|
||||||
import androidx.annotation.LayoutRes
|
|
||||||
import androidx.core.os.ConfigurationCompat
|
|
||||||
import fr.free.nrw.commons.R
|
|
||||||
import fr.free.nrw.commons.utils.LangCodeUtils
|
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
|
||||||
import kotlinx.android.synthetic.main.row_item_languages_spinner.*
|
|
||||||
import org.apache.commons.lang3.StringUtils
|
|
||||||
import org.wikipedia.language.AppLanguageLookUpTable
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class handles the display of language spinners and their dropdown views for UploadMediaDetailFragment
|
|
||||||
*
|
|
||||||
* @property selectedLanguages - controls the enabled state of dropdown views
|
|
||||||
*
|
|
||||||
* @param context - required by super constructor
|
|
||||||
*/
|
|
||||||
class SpinnerLanguagesAdapter constructor(
|
|
||||||
context: Context,
|
|
||||||
private val selectedLanguages: HashMap<*, String>
|
|
||||||
) : ArrayAdapter<Any?>(context, -1) {
|
|
||||||
|
|
||||||
private val languageNamesList: List<String>
|
|
||||||
private val languageCodesList: List<String>
|
|
||||||
var language: AppLanguageLookUpTable = AppLanguageLookUpTable(context)
|
|
||||||
init {
|
|
||||||
languageNamesList = language.localizedNames;
|
|
||||||
languageCodesList = language.codes;
|
|
||||||
}
|
|
||||||
|
|
||||||
var selectedLangCode = ""
|
|
||||||
|
|
||||||
override fun isEnabled(position: Int) = languageCodesList[position].let {
|
|
||||||
it.isNotEmpty() && !selectedLanguages.containsValue(it) && it != selectedLangCode
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getCount() = languageNamesList.size
|
|
||||||
|
|
||||||
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup) =
|
|
||||||
(convertView ?: parent.inflate(R.layout.row_item_languages_spinner).also {
|
|
||||||
it.tag = DropDownViewHolder(it)
|
|
||||||
}).apply {
|
|
||||||
(tag as DropDownViewHolder).init(
|
|
||||||
languageCodesList[position],
|
|
||||||
languageNamesList[position],
|
|
||||||
isEnabled(position)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup) =
|
|
||||||
(convertView ?: parent.inflate(R.layout.row_item_languages_spinner).also {
|
|
||||||
it.tag = SpinnerViewHolder(it)
|
|
||||||
}).apply { (tag as SpinnerViewHolder).init(languageCodesList[position]) }
|
|
||||||
|
|
||||||
class SpinnerViewHolder(override val containerView: View) : LayoutContainer {
|
|
||||||
fun init(languageCode: String) {
|
|
||||||
LangCodeUtils.fixLanguageCode(languageCode).let {
|
|
||||||
tv_language.text = if (it.length > 2) it.take(2) else it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DropDownViewHolder(override val containerView: View) : LayoutContainer {
|
|
||||||
fun init(languageCode: String, languageName: String, enabled: Boolean) {
|
|
||||||
tv_language.isEnabled = enabled
|
|
||||||
if (languageCode.isEmpty()) {
|
|
||||||
tv_language.text = StringUtils.capitalize(languageName)
|
|
||||||
tv_language.textAlignment = View.TEXT_ALIGNMENT_CENTER
|
|
||||||
} else {
|
|
||||||
tv_language.text =
|
|
||||||
"${StringUtils.capitalize(languageName)}" +
|
|
||||||
" [${LangCodeUtils.fixLanguageCode(languageCode)}]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLanguageCode(position: Int): String {
|
|
||||||
return languageCodesList[position]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getIndexOfUserDefaultLocale(context: Context): Int {
|
|
||||||
return languageCodesList.indexOf(context.locale.language)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getIndexOfLanguageCode(languageCode: String): Int {
|
|
||||||
return languageCodesList.indexOf(languageCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ViewGroup.inflate(@LayoutRes resId: Int) =
|
|
||||||
LayoutInflater.from(context).inflate(resId, this, false)
|
|
||||||
|
|
||||||
private val Context.locale: Locale
|
|
||||||
get() = ConfigurationCompat.getLocales(resources.configuration)[0]
|
|
||||||
|
|
@ -1,13 +1,19 @@
|
||||||
package fr.free.nrw.commons.upload;
|
package fr.free.nrw.commons.upload;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.text.Editable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.text.TextWatcher;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemSelectedListener;
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.Spinner;
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
@ -28,7 +34,7 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
private EventListener eventListener;
|
private EventListener eventListener;
|
||||||
|
|
||||||
private HashMap<AdapterView, String> selectedLanguages;
|
private HashMap<Integer, String> selectedLanguages;
|
||||||
private final String savedLanguageValue;
|
private final String savedLanguageValue;
|
||||||
|
|
||||||
public UploadMediaDetailAdapter(String savedLanguageValue) {
|
public UploadMediaDetailAdapter(String savedLanguageValue) {
|
||||||
|
|
@ -80,6 +86,7 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDescription(UploadMediaDetail uploadMediaDetail) {
|
public void addDescription(UploadMediaDetail uploadMediaDetail) {
|
||||||
|
selectedLanguages.put(uploadMediaDetails.size(), "en");
|
||||||
this.uploadMediaDetails.add(uploadMediaDetail);
|
this.uploadMediaDetails.add(uploadMediaDetail);
|
||||||
notifyItemInserted(uploadMediaDetails.size());
|
notifyItemInserted(uploadMediaDetails.size());
|
||||||
}
|
}
|
||||||
|
|
@ -91,6 +98,7 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
||||||
* @param position
|
* @param position
|
||||||
*/
|
*/
|
||||||
public void removeDescription(final UploadMediaDetail uploadMediaDetail, final int position) {
|
public void removeDescription(final UploadMediaDetail uploadMediaDetail, final int position) {
|
||||||
|
selectedLanguages.remove(position);
|
||||||
this.uploadMediaDetails.remove(uploadMediaDetail);
|
this.uploadMediaDetails.remove(uploadMediaDetail);
|
||||||
notifyItemRemoved(position);
|
notifyItemRemoved(position);
|
||||||
}
|
}
|
||||||
|
|
@ -98,8 +106,8 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
||||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@BindView(R.id.spinner_description_languages)
|
@BindView(R.id.description_languages)
|
||||||
Spinner spinnerDescriptionLanguages;
|
TextView descriptionLanguages;
|
||||||
|
|
||||||
@BindView(R.id.description_item_edit_text)
|
@BindView(R.id.description_item_edit_text)
|
||||||
PasteSensitiveTextInputEditText descItemEditText;
|
PasteSensitiveTextInputEditText descItemEditText;
|
||||||
|
|
@ -126,6 +134,7 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
||||||
UploadMediaDetail uploadMediaDetail = uploadMediaDetails.get(position);
|
UploadMediaDetail uploadMediaDetail = uploadMediaDetails.get(position);
|
||||||
Timber.d("UploadMediaDetail is " + uploadMediaDetail);
|
Timber.d("UploadMediaDetail is " + uploadMediaDetail);
|
||||||
|
|
||||||
|
descriptionLanguages.setFocusable(false);
|
||||||
captionItemEditText.addTextChangedListener(new AbstractTextWatcher(
|
captionItemEditText.addTextChangedListener(new AbstractTextWatcher(
|
||||||
value -> {
|
value -> {
|
||||||
if (position == 0) {
|
if (position == 0) {
|
||||||
|
|
@ -157,11 +166,11 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
||||||
|
|
||||||
captionItemEditText.addTextChangedListener(new AbstractTextWatcher(
|
captionItemEditText.addTextChangedListener(new AbstractTextWatcher(
|
||||||
captionText -> uploadMediaDetails.get(position).setCaptionText(captionText)));
|
captionText -> uploadMediaDetails.get(position).setCaptionText(captionText)));
|
||||||
initLanguageSpinner(position, uploadMediaDetail);
|
initLanguage(position, uploadMediaDetail);
|
||||||
|
|
||||||
descItemEditText.addTextChangedListener(new AbstractTextWatcher(
|
descItemEditText.addTextChangedListener(new AbstractTextWatcher(
|
||||||
descriptionText -> uploadMediaDetails.get(position).setDescriptionText(descriptionText)));
|
descriptionText -> uploadMediaDetails.get(position).setDescriptionText(descriptionText)));
|
||||||
initLanguageSpinner(position, uploadMediaDetail);
|
initLanguage(position, uploadMediaDetail);
|
||||||
|
|
||||||
//If the description was manually added by the user, it deserves focus, if not, let the user decide
|
//If the description was manually added by the user, it deserves focus, if not, let the user decide
|
||||||
if (uploadMediaDetail.isManuallyAdded()) {
|
if (uploadMediaDetail.isManuallyAdded()) {
|
||||||
|
|
@ -171,78 +180,124 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracted out the function to init the language spinner with different system supported languages
|
private void initLanguage(int position, UploadMediaDetail description) {
|
||||||
* @param position
|
|
||||||
* @param description
|
LanguagesAdapter languagesAdapter = new LanguagesAdapter(
|
||||||
*/
|
descriptionLanguages.getContext(),
|
||||||
private void initLanguageSpinner(int position, UploadMediaDetail description) {
|
|
||||||
SpinnerLanguagesAdapter languagesAdapter = new SpinnerLanguagesAdapter(
|
|
||||||
spinnerDescriptionLanguages.getContext(),
|
|
||||||
selectedLanguages
|
selectedLanguages
|
||||||
);
|
);
|
||||||
spinnerDescriptionLanguages.setAdapter(languagesAdapter);
|
|
||||||
|
|
||||||
spinnerDescriptionLanguages.setOnItemSelectedListener(new OnItemSelectedListener() {
|
descriptionLanguages.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> adapterView, View view, int position,
|
public void onClick(View view) {
|
||||||
long l) {
|
Dialog dialog = new Dialog(view.getContext());
|
||||||
description.setSelectedLanguageIndex(position);
|
dialog.setContentView(R.layout.dialog_select_language);
|
||||||
String languageCode = ((SpinnerLanguagesAdapter) adapterView.getAdapter())
|
dialog.setCanceledOnTouchOutside(true);
|
||||||
.getLanguageCode(position);
|
dialog.getWindow().setLayout((int)(view.getContext().getResources().getDisplayMetrics().widthPixels*0.90),
|
||||||
description.setLanguageCode(languageCode);
|
(int)(view.getContext().getResources().getDisplayMetrics().heightPixels*0.90));
|
||||||
selectedLanguages.remove(adapterView);
|
dialog.show();
|
||||||
selectedLanguages.put(adapterView, languageCode);
|
|
||||||
((SpinnerLanguagesAdapter) adapterView
|
EditText editText = dialog.findViewById(R.id.search_language);
|
||||||
.getAdapter()).setSelectedLangCode(languageCode);
|
ListView listView = dialog.findViewById(R.id.language_list);
|
||||||
spinnerDescriptionLanguages.setSelection(position);
|
|
||||||
Timber.d("Description language code is: " + languageCode);
|
listView.setAdapter(languagesAdapter);
|
||||||
|
|
||||||
|
editText.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
|
||||||
|
int i2) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
public void onTextChanged(CharSequence charSequence, int i, int i1,
|
||||||
|
int i2) {
|
||||||
|
languagesAdapter.getFilter().filter(charSequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable editable) {
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
listView.setOnItemClickListener(new OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> adapterView, View view, int i,
|
||||||
|
long l) {
|
||||||
|
description.setSelectedLanguageIndex(i);
|
||||||
|
String languageCode = ((LanguagesAdapter) adapterView.getAdapter())
|
||||||
|
.getLanguageCode(i);
|
||||||
|
description.setLanguageCode(languageCode);
|
||||||
|
selectedLanguages.remove(position);
|
||||||
|
selectedLanguages.put(position, languageCode);
|
||||||
|
((LanguagesAdapter) adapterView
|
||||||
|
.getAdapter()).setSelectedLangCode(languageCode);
|
||||||
|
Timber.d("Description language code is: " + languageCode);
|
||||||
|
descriptionLanguages.setText(languageCode);
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.setOnDismissListener(
|
||||||
|
dialogInterface -> languagesAdapter.getFilter().filter(""));
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (description.getSelectedLanguageIndex() == -1) {
|
if (description.getSelectedLanguageIndex() == -1) {
|
||||||
if (!TextUtils.isEmpty(savedLanguageValue)) {
|
if (!TextUtils.isEmpty(savedLanguageValue)) {
|
||||||
// If user has chosen a default language from settings activity
|
// If user has chosen a default language from settings activity
|
||||||
// savedLanguageValue is not null
|
// savedLanguageValue is not null
|
||||||
if(!TextUtils.isEmpty(description.getLanguageCode())) {
|
if(!TextUtils.isEmpty(description.getLanguageCode())) {
|
||||||
spinnerDescriptionLanguages.setSelection(languagesAdapter
|
descriptionLanguages.setText(description.getLanguageCode());
|
||||||
.getIndexOfLanguageCode(description.getLanguageCode()));
|
selectedLanguages.remove(position);
|
||||||
|
selectedLanguages.put(position, description.getLanguageCode());
|
||||||
} else {
|
} else {
|
||||||
spinnerDescriptionLanguages.setSelection(languagesAdapter
|
description.setLanguageCode(savedLanguageValue);
|
||||||
.getIndexOfLanguageCode(savedLanguageValue));
|
descriptionLanguages.setText(savedLanguageValue);
|
||||||
|
selectedLanguages.remove(position);
|
||||||
|
selectedLanguages.put(position, savedLanguageValue);
|
||||||
}
|
}
|
||||||
} else if (!TextUtils.isEmpty(description.getLanguageCode())) {
|
} else if (!TextUtils.isEmpty(description.getLanguageCode())) {
|
||||||
spinnerDescriptionLanguages.setSelection(languagesAdapter
|
descriptionLanguages.setText(description.getLanguageCode());
|
||||||
.getIndexOfLanguageCode(description.getLanguageCode()));
|
selectedLanguages.remove(position);
|
||||||
|
selectedLanguages.put(position, description.getLanguageCode());
|
||||||
} else {
|
} else {
|
||||||
//Checking whether Language Code attribute is null or not.
|
//Checking whether Language Code attribute is null or not.
|
||||||
if (uploadMediaDetails.get(position).getLanguageCode() != null) {
|
if (uploadMediaDetails.get(position).getLanguageCode() != null) {
|
||||||
//If it is not null that means it is fetching details from the previous
|
//If it is not null that means it is fetching details from the previous
|
||||||
// upload (i.e. when user has pressed copy previous caption & description)
|
// upload (i.e. when user has pressed copy previous caption & description)
|
||||||
//hence providing same language code for the current upload.
|
//hence providing same language code for the current upload.
|
||||||
spinnerDescriptionLanguages.setSelection(languagesAdapter
|
descriptionLanguages.setText(uploadMediaDetails.get(position)
|
||||||
.getIndexOfLanguageCode(uploadMediaDetails.get(position)
|
.getLanguageCode());
|
||||||
.getLanguageCode()), true);
|
selectedLanguages.remove(position);
|
||||||
|
selectedLanguages.put(position, uploadMediaDetails.get(position)
|
||||||
|
.getLanguageCode());
|
||||||
} else {
|
} else {
|
||||||
if (position == 0) {
|
if (position == 0) {
|
||||||
final int defaultLocaleIndex = languagesAdapter
|
final int defaultLocaleIndex = languagesAdapter
|
||||||
.getIndexOfUserDefaultLocale(spinnerDescriptionLanguages
|
.getIndexOfUserDefaultLocale(descriptionLanguages
|
||||||
.getContext());
|
.getContext());
|
||||||
spinnerDescriptionLanguages.setSelection(defaultLocaleIndex, true);
|
descriptionLanguages
|
||||||
|
.setText(languagesAdapter.getLanguageCode(defaultLocaleIndex));
|
||||||
|
description.setLanguageCode(languagesAdapter.getLanguageCode(defaultLocaleIndex));
|
||||||
|
selectedLanguages.remove(position);
|
||||||
|
selectedLanguages.put(position, languagesAdapter.getLanguageCode(defaultLocaleIndex));
|
||||||
} else {
|
} else {
|
||||||
spinnerDescriptionLanguages.setSelection(0, true);
|
description.setLanguageCode(languagesAdapter.getLanguageCode(0));
|
||||||
|
descriptionLanguages.setText(languagesAdapter.getLanguageCode(0));
|
||||||
|
selectedLanguages.remove(position);
|
||||||
|
selectedLanguages.put(position, languagesAdapter.getLanguageCode(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
spinnerDescriptionLanguages.setSelection(description.getSelectedLanguageIndex());
|
descriptionLanguages.setText(description.getLanguageCode());
|
||||||
selectedLanguages.put(spinnerDescriptionLanguages, description.getLanguageCode());
|
selectedLanguages.remove(position);
|
||||||
|
selectedLanguages.put(position, description.getLanguageCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
app/src/main/res/drawable/ic_baseline_arrow_drop_down_24.xml
Normal file
10
app/src/main/res/drawable/ic_baseline_arrow_drop_down_24.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M7,10l5,5 5,-5z"/>
|
||||||
|
</vector>
|
||||||
31
app/src/main/res/layout/dialog_select_language.xml
Normal file
31
app/src/main/res/layout/dialog_select_language.xml
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/search_language"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:hint="Type Language Name"
|
||||||
|
android:padding="12dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"></EditText>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:id="@+id/language_list"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/search_language" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -23,11 +23,14 @@
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:srcCompat="@drawable/ic_remove" />
|
app:srcCompat="@drawable/ic_remove" />
|
||||||
|
|
||||||
<Spinner
|
<TextView
|
||||||
android:id="@+id/spinner_description_languages"
|
android:id="@+id/description_languages"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:spinnerMode="dialog"
|
android:clickable="true"
|
||||||
|
android:drawableRight="@drawable/ic_baseline_arrow_drop_down_24"
|
||||||
|
android:padding="@dimen/dimen_2"
|
||||||
|
android:textSize="18sp"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/caption_item_edit_text_input_layout"
|
app:layout_constraintBottom_toTopOf="@+id/caption_item_edit_text_input_layout"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,13 @@
|
||||||
android:summary="@string/use_external_storage_summary"
|
android:summary="@string/use_external_storage_summary"
|
||||||
android:title="@string/use_external_storage" />
|
android:title="@string/use_external_storage" />
|
||||||
|
|
||||||
<ListPreference
|
<Preference
|
||||||
android:key="appUiDefaultLanguagePref"
|
android:key="appUiDefaultLanguagePref"
|
||||||
app:useSimpleSummaryProvider="true"
|
app:useSimpleSummaryProvider="true"
|
||||||
app:singleLineTitle="false"
|
app:singleLineTitle="false"
|
||||||
android:title="@string/app_ui_language" />
|
android:title="@string/app_ui_language" />
|
||||||
|
|
||||||
<ListPreference
|
<Preference
|
||||||
android:key="descriptionDefaultLanguagePref"
|
android:key="descriptionDefaultLanguagePref"
|
||||||
app:useSimpleSummaryProvider="true"
|
app:useSimpleSummaryProvider="true"
|
||||||
app:singleLineTitle="false"
|
app:singleLineTitle="false"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
package fr.free.nrw.commons.upload
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.ConfigurationCompat
|
||||||
|
import fr.free.nrw.commons.R
|
||||||
|
import fr.free.nrw.commons.TestCommonsApplication
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.jupiter.api.Assertions
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.`when`
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.RuntimeEnvironment
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
import org.robolectric.annotation.LooperMode
|
||||||
|
import org.wikipedia.language.AppLanguageLookUpTable
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
@Config(sdk = [21], application = TestCommonsApplication::class)
|
||||||
|
@LooperMode(LooperMode.Mode.PAUSED)
|
||||||
|
class LanguagesAdapterTest {
|
||||||
|
|
||||||
|
private lateinit var context: Context
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private lateinit var selectedLanguages: HashMap<Integer, String>
|
||||||
|
@Mock
|
||||||
|
private lateinit var parent: ViewGroup
|
||||||
|
|
||||||
|
private lateinit var languageNamesList: List<String>
|
||||||
|
private lateinit var languageCodesList: List<String>
|
||||||
|
private lateinit var language: AppLanguageLookUpTable
|
||||||
|
|
||||||
|
private lateinit var languagesAdapter: LanguagesAdapter
|
||||||
|
private lateinit var convertView: View
|
||||||
|
private var selectLanguages: HashMap<Integer, String> = HashMap()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
@Throws(Exception::class)
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
context = RuntimeEnvironment.application.applicationContext
|
||||||
|
language = AppLanguageLookUpTable(context)
|
||||||
|
convertView = LayoutInflater.from(context)
|
||||||
|
.inflate(R.layout.row_item_languages_spinner, null) as View
|
||||||
|
|
||||||
|
languageNamesList = language.localizedNames
|
||||||
|
languageCodesList = language.codes
|
||||||
|
|
||||||
|
languagesAdapter = LanguagesAdapter(context, selectedLanguages)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Throws(Exception::class)
|
||||||
|
fun testOnGetView() {
|
||||||
|
languagesAdapter = LanguagesAdapter(context, selectedLanguages)
|
||||||
|
`when`(selectedLanguages.values).thenReturn(Collections.emptyList())
|
||||||
|
Assert.assertEquals(languagesAdapter.getView(0, convertView, parent), convertView)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetCount() {
|
||||||
|
Assertions.assertEquals(languageCodesList.size, languagesAdapter.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetLanguageCode() {
|
||||||
|
languagesAdapter = LanguagesAdapter(context, selectedLanguages)
|
||||||
|
Assertions.assertEquals(languagesAdapter.getLanguageCode(0), languageCodesList[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetIndexOfUserDefaultLocale() {
|
||||||
|
languagesAdapter = LanguagesAdapter(context, selectedLanguages)
|
||||||
|
Assertions.assertEquals(languageCodesList.indexOf(ConfigurationCompat.getLocales(context.resources.configuration)[0].language), languagesAdapter.getIndexOfUserDefaultLocale(context))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSelectLanguageNotEmpty() {
|
||||||
|
selectLanguages[Integer(0)] = "es"
|
||||||
|
selectLanguages[Integer(1)] = "de"
|
||||||
|
languagesAdapter = LanguagesAdapter(context, selectLanguages)
|
||||||
|
|
||||||
|
Assertions.assertEquals(false, languagesAdapter.isEnabled(languagesAdapter.getIndexOfLanguageCode("es")))
|
||||||
|
Assertions.assertEquals(false, languagesAdapter.isEnabled(languagesAdapter.getIndexOfLanguageCode("de")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFilterEmpty() {
|
||||||
|
languagesAdapter = LanguagesAdapter(context, selectedLanguages)
|
||||||
|
languagesAdapter.filter.filter("")
|
||||||
|
Assertions.assertEquals(languageCodesList.size, languagesAdapter.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFilterNonEmpty() {
|
||||||
|
languagesAdapter = LanguagesAdapter(context, selectedLanguages)
|
||||||
|
val constraint = "spa"
|
||||||
|
languagesAdapter.filter.filter(constraint)
|
||||||
|
val length: Int = languageNamesList.size
|
||||||
|
val defaultlanguagecode = languageCodesList.indexOf(ConfigurationCompat.getLocales(context.resources.configuration)[0].language)
|
||||||
|
var i = 0
|
||||||
|
var s = 0
|
||||||
|
while (i < length) {
|
||||||
|
val key: String = language.codes[i]
|
||||||
|
val value: String = language.localizedNames[i]
|
||||||
|
if(value.contains(constraint, true) || Locale(key).getDisplayName(
|
||||||
|
Locale(language.codes[defaultlanguagecode])).contains(constraint, true))
|
||||||
|
s++
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
Assertions.assertEquals(s, languagesAdapter.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue