diff --git a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java index 3cbc0a376..2d3856506 100644 --- a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java @@ -4,17 +4,24 @@ import static android.content.Context.MODE_PRIVATE; import android.Manifest; import android.app.Activity; +import android.app.Dialog; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; 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.MultiSelectListPreference; import androidx.preference.Preference; -import androidx.preference.Preference.OnPreferenceChangeListener; +import androidx.preference.Preference.OnPreferenceClickListener; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceGroupAdapter; 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.kvstore.JsonKvStore; 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.ViewUtil; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Objects; import javax.inject.Inject; import javax.inject.Named; -import org.wikipedia.language.AppLanguageLookUpTable; public class SettingsFragment extends PreferenceFragmentCompat { @@ -53,8 +61,8 @@ public class SettingsFragment extends PreferenceFragmentCompat { CommonsLogSender commonsLogSender; private ListPreference themeListPreference; - private ListPreference descriptionLanguageListPreference; - private ListPreference appUiLanguageListPreference; + private Preference descriptionLanguageListPreference; + private Preference appUiLanguageListPreference; private String keyLanguageListPreference; @Override @@ -80,15 +88,50 @@ public class SettingsFragment extends PreferenceFragmentCompat { }); } + // Gets current language code from shared preferences + String languageCode; + appUiLanguageListPreference = findPreference("appUiDefaultLanguagePref"); assert appUiLanguageListPreference != null; 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"); assert descriptionLanguageListPreference != null; 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"); 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. + * Disable default/already selected language from dialog box * 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 * @param keyListPreference */ private void prepareAppLanguages(final String keyListPreference) { - final List languageNamesList; - final List languageCodesList; - final AppLanguageLookUpTable appLanguageLookUpTable = new AppLanguageLookUpTable( - Objects.requireNonNull(getContext())); - languageNamesList = appLanguageLookUpTable.getLocalizedNames(); - languageCodesList = appLanguageLookUpTable.getCodes(); - List 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 final String languageCode = getCurrentLanguageCode(keyListPreference); + HashMap selectedLanguages = new HashMap<>(); if (keyListPreference.equals("appUiDefaultLanguagePref")) { - appUiLanguageListPreference.setEntries(languageNames); - appUiLanguageListPreference.setEntryValues(languageCodes); assert languageCode != null; if (languageCode.equals("")) { - // If current language code is empty, means none selected by user yet so use phone local - appUiLanguageListPreference.setValue(Locale.getDefault().getLanguage()); + selectedLanguages.put(0, Locale.getDefault().getLanguage()); } else { - // If any language is selected by user previously, use it - appUiLanguageListPreference.setValue(languageCode); + selectedLanguages.put(0, languageCode); } - - appUiLanguageListPreference.setOnPreferenceChangeListener((preference, newValue) -> { - final String userSelectedValue = (String) newValue; - setLocale(Objects.requireNonNull(getActivity()), userSelectedValue); - saveLanguageValue(userSelectedValue, keyListPreference); - getActivity().recreate(); - final Intent intent = new Intent(getActivity(), MainActivity.class); - 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()); + selectedLanguages.put(0, Locale.getDefault().getLanguage()); + } else { - // If any language is selected by user previously, use it - descriptionLanguageListPreference.setValue(languageCode); + selectedLanguages.put(0, languageCode); + } + } + + LanguagesAdapter languagesAdapter = new LanguagesAdapter( + getActivity(), + selectedLanguages + ); + + 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) { + } - descriptionLanguageListPreference.setOnPreferenceChangeListener((preference, newValue) -> { - final String userSelectedValue = (String) newValue; - saveLanguageValue(userSelectedValue, keyListPreference); - return true; - }); - } + @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(); + final Intent intent = new Intent(getActivity(), MainActivity.class); + startActivity(intent); + }else { + descriptionLanguageListPreference.setSummary(defLocale.getDisplayLanguage(defLocale)); + } + dialog.dismiss(); + } + }); + + dialog.setOnDismissListener( + dialogInterface -> languagesAdapter.getFilter().filter("")); } /** diff --git a/app/src/main/java/fr/free/nrw/commons/upload/LanguagesAdapter.kt b/app/src/main/java/fr/free/nrw/commons/upload/LanguagesAdapter.kt new file mode 100644 index 000000000..447618dd4 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/upload/LanguagesAdapter.kt @@ -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(context, R.layout.row_item_languages_spinner) { + + private var languageNamesList: List + private var languageCodesList: List + + 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 = 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).keys) + languageNamesList = + ArrayList((results.values as LinkedHashMap).values) + notifyDataSetChanged() + } else { + languageCodesList = ArrayList() + languageNamesList = ArrayList() + notifyDataSetChanged() + } + + } + + } + +} + +private val Context.locale: Locale + get() = ConfigurationCompat.getLocales(resources.configuration)[0] diff --git a/app/src/main/java/fr/free/nrw/commons/upload/SpinnerLanguagesAdapter.kt b/app/src/main/java/fr/free/nrw/commons/upload/SpinnerLanguagesAdapter.kt deleted file mode 100644 index 82fc51f13..000000000 --- a/app/src/main/java/fr/free/nrw/commons/upload/SpinnerLanguagesAdapter.kt +++ /dev/null @@ -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(context, -1) { - - private val languageNamesList: List - private val languageCodesList: List - 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] diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java index 289c816bb..5a8d0ef6d 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java @@ -1,13 +1,19 @@ package fr.free.nrw.commons.upload; +import android.app.Dialog; +import android.text.Editable; import android.text.TextUtils; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; 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.Spinner; +import android.widget.ListView; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; @@ -28,7 +34,7 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter selectedLanguages; + private HashMap selectedLanguages; private final String savedLanguageValue; public UploadMediaDetailAdapter(String savedLanguageValue) { @@ -80,6 +86,7 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter { if (position == 0) { @@ -157,11 +166,11 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter uploadMediaDetails.get(position).setCaptionText(captionText))); - initLanguageSpinner(position, uploadMediaDetail); + initLanguage(position, uploadMediaDetail); descItemEditText.addTextChangedListener(new AbstractTextWatcher( 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 (uploadMediaDetail.isManuallyAdded()) { @@ -171,78 +180,124 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter adapterView, View view, int position, - long l) { - description.setSelectedLanguageIndex(position); - String languageCode = ((SpinnerLanguagesAdapter) adapterView.getAdapter()) - .getLanguageCode(position); - description.setLanguageCode(languageCode); - selectedLanguages.remove(adapterView); - selectedLanguages.put(adapterView, languageCode); - ((SpinnerLanguagesAdapter) adapterView - .getAdapter()).setSelectedLangCode(languageCode); - spinnerDescriptionLanguages.setSelection(position); - Timber.d("Description language code is: " + languageCode); - } + public void onClick(View view) { + Dialog dialog = new Dialog(view.getContext()); + dialog.setContentView(R.layout.dialog_select_language); + dialog.setCanceledOnTouchOutside(true); + dialog.getWindow().setLayout((int)(view.getContext().getResources().getDisplayMetrics().widthPixels*0.90), + (int)(view.getContext().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) { + 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("")); - @Override - public void onNothingSelected(AdapterView adapterView) { } }); - if (description.getSelectedLanguageIndex() == -1) { if (!TextUtils.isEmpty(savedLanguageValue)) { // If user has chosen a default language from settings activity // savedLanguageValue is not null if(!TextUtils.isEmpty(description.getLanguageCode())) { - spinnerDescriptionLanguages.setSelection(languagesAdapter - .getIndexOfLanguageCode(description.getLanguageCode())); + descriptionLanguages.setText(description.getLanguageCode()); + selectedLanguages.remove(position); + selectedLanguages.put(position, description.getLanguageCode()); } else { - spinnerDescriptionLanguages.setSelection(languagesAdapter - .getIndexOfLanguageCode(savedLanguageValue)); + description.setLanguageCode(savedLanguageValue); + descriptionLanguages.setText(savedLanguageValue); + selectedLanguages.remove(position); + selectedLanguages.put(position, savedLanguageValue); } } else if (!TextUtils.isEmpty(description.getLanguageCode())) { - spinnerDescriptionLanguages.setSelection(languagesAdapter - .getIndexOfLanguageCode(description.getLanguageCode())); + descriptionLanguages.setText(description.getLanguageCode()); + selectedLanguages.remove(position); + selectedLanguages.put(position, description.getLanguageCode()); } else { //Checking whether Language Code attribute is null or not. if (uploadMediaDetails.get(position).getLanguageCode() != null) { //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) //hence providing same language code for the current upload. - spinnerDescriptionLanguages.setSelection(languagesAdapter - .getIndexOfLanguageCode(uploadMediaDetails.get(position) - .getLanguageCode()), true); + descriptionLanguages.setText(uploadMediaDetails.get(position) + .getLanguageCode()); + selectedLanguages.remove(position); + selectedLanguages.put(position, uploadMediaDetails.get(position) + .getLanguageCode()); } else { if (position == 0) { final int defaultLocaleIndex = languagesAdapter - .getIndexOfUserDefaultLocale(spinnerDescriptionLanguages - .getContext()); - spinnerDescriptionLanguages.setSelection(defaultLocaleIndex, true); + .getIndexOfUserDefaultLocale(descriptionLanguages + .getContext()); + descriptionLanguages + .setText(languagesAdapter.getLanguageCode(defaultLocaleIndex)); + description.setLanguageCode(languagesAdapter.getLanguageCode(defaultLocaleIndex)); + selectedLanguages.remove(position); + selectedLanguages.put(position, languagesAdapter.getLanguageCode(defaultLocaleIndex)); } 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 { - spinnerDescriptionLanguages.setSelection(description.getSelectedLanguageIndex()); - selectedLanguages.put(spinnerDescriptionLanguages, description.getLanguageCode()); + descriptionLanguages.setText(description.getLanguageCode()); + selectedLanguages.remove(position); + selectedLanguages.put(position, description.getLanguageCode()); } } } diff --git a/app/src/main/res/drawable/ic_baseline_arrow_drop_down_24.xml b/app/src/main/res/drawable/ic_baseline_arrow_drop_down_24.xml new file mode 100644 index 000000000..ce583469c --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_arrow_drop_down_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/dialog_select_language.xml b/app/src/main/res/layout/dialog_select_language.xml new file mode 100644 index 000000000..a2314aa55 --- /dev/null +++ b/app/src/main/res/layout/dialog_select_language.xml @@ -0,0 +1,31 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/row_item_description.xml b/app/src/main/res/layout/row_item_description.xml index 9b9ac1915..d0b9d4c8f 100644 --- a/app/src/main/res/layout/row_item_description.xml +++ b/app/src/main/res/layout/row_item_description.xml @@ -23,11 +23,14 @@ app:layout_constraintEnd_toEndOf="parent" app:srcCompat="@drawable/ic_remove" /> - diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index be8470ced..dccfea1d4 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -26,13 +26,13 @@ android:summary="@string/use_external_storage_summary" android:title="@string/use_external_storage" /> - - + @Mock + private lateinit var parent: ViewGroup + + private lateinit var languageNamesList: List + private lateinit var languageCodesList: List + private lateinit var language: AppLanguageLookUpTable + + private lateinit var languagesAdapter: LanguagesAdapter + private lateinit var convertView: View + private var selectLanguages: HashMap = 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) + } + +} \ No newline at end of file