From 50e175509ba96a2871a18dccffe070d2a60a571c Mon Sep 17 00:00:00 2001 From: Helium314 Date: Fri, 1 Sep 2023 19:49:37 +0200 Subject: [PATCH] make language settings work nicely again now actually it's not part of preferences any more, but looks the same --- .../latin/BinaryDictionaryGetter.java | 2 +- ...ent.kt => LanguageFakeSettingsFragment.kt} | 59 ++++++++++++------ ...istPreference.kt => LanguageFilterList.kt} | 60 ++++--------------- .../latin/settings/LanguageSettingsDialog.kt | 4 +- .../latin/settings/SettingsActivity.java | 1 + .../latin/settings/SubScreenFragment.java | 4 +- .../latin/utils/FragmentUtils.java | 4 +- .../res/layout/language_fake_settings.xml | 20 +++++++ .../res/layout/language_search_filter.xml | 2 +- app/src/main/res/xml/prefs.xml | 2 +- 10 files changed, 83 insertions(+), 75 deletions(-) rename app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/{LanguageSettingsFragment.kt => LanguageFakeSettingsFragment.kt} (76%) rename app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/{LanguageFilterListPreference.kt => LanguageFilterList.kt} (67%) create mode 100644 app/src/main/res/layout/language_fake_settings.xml diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/BinaryDictionaryGetter.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/BinaryDictionaryGetter.java index ba5a57e85..723031dce 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/BinaryDictionaryGetter.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/BinaryDictionaryGetter.java @@ -16,7 +16,7 @@ package org.dslul.openboard.inputmethod.latin; -import static org.dslul.openboard.inputmethod.latin.settings.LanguageSettingsFragmentKt.USER_DICTIONARY_SUFFIX; +import static org.dslul.openboard.inputmethod.latin.settings.LanguageFakeSettingsFragmentKt.USER_DICTIONARY_SUFFIX; import android.content.Context; import android.content.SharedPreferences; diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsFragment.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFakeSettingsFragment.kt similarity index 76% rename from app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsFragment.kt rename to app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFakeSettingsFragment.kt index df18e1a99..52b36dcca 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsFragment.kt +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFakeSettingsFragment.kt @@ -6,51 +6,76 @@ import android.content.Intent import android.content.SharedPreferences import android.net.Uri import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup import android.view.inputmethod.InputMethodSubtype -import androidx.preference.SwitchPreferenceCompat +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.SwitchCompat +import androidx.core.content.edit +import androidx.fragment.app.Fragment import org.dslul.openboard.inputmethod.latin.R import org.dslul.openboard.inputmethod.latin.common.LocaleUtils +import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils import org.dslul.openboard.inputmethod.latin.utils.DictionaryInfoUtils import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils import org.dslul.openboard.inputmethod.latin.utils.getDictionaryLocales -import java.util.Locale - -class LanguageSettingsFragment : SubScreenFragment() { +import java.util.* +// not a SettingsFragment, because with androidx.preferences it's very complicated or +// impossible to have the languages RecyclerView scrollable (this way it works nicely out of the box) +class LanguageFakeSettingsFragment : Fragment(R.layout.language_fake_settings) { private val sortedSubtypes = LinkedHashMap>() private val enabledSubtypes = mutableListOf() private val systemLocales = mutableListOf() - private val languageFilterListPreference by lazy { findPreference("pref_language_filter")!! } + private lateinit var languageFilterList: LanguageFilterListFakePreference + private lateinit var sharedPreferences: SharedPreferences + private lateinit var systemOnlySwitch: SwitchCompat private val dictionaryLocales by lazy { getDictionaryLocales(requireContext()).mapTo(HashSet()) { it.languageConsideringZZ() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - addPreferencesFromResource(R.xml.prefs_screen_languages) + sharedPreferences = DeviceProtectedUtils.getSharedPreferences(requireContext()) + SubtypeLocaleUtils.init(requireContext()) enabledSubtypes.addAll(getEnabledSubtypes(sharedPreferences)) systemLocales.addAll(getSystemLocales()) - loadSubtypes() } - override fun onSharedPreferenceChanged(prefs: SharedPreferences, key: String) { - super.onSharedPreferenceChanged(prefs, key) - if (key == Settings.PREF_USE_SYSTEM_LOCALES) - loadSubtypes() + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = super.onCreateView(inflater, container, savedInstanceState) ?: return null + systemOnlySwitch = view.findViewById(R.id.language_switch) + systemOnlySwitch.isChecked = sharedPreferences.getBoolean(Settings.PREF_USE_SYSTEM_LOCALES, true) + systemOnlySwitch.setOnCheckedChangeListener { _, b -> + sharedPreferences.edit { putBoolean(Settings.PREF_USE_SYSTEM_LOCALES, b) } + loadSubtypes(b) + } + languageFilterList = LanguageFilterListFakePreference(view.findViewById(R.id.search_field), view.findViewById(R.id.language_list)) + loadSubtypes(systemOnlySwitch.isChecked) + return view } override fun onResume() { super.onResume() - languageFilterListPreference.setSettingsFragment(this) + languageFilterList.setSettingsFragment(this) + val activity: Activity? = activity + if (activity is AppCompatActivity) { + val actionBar = activity.supportActionBar ?: return + actionBar.setTitle(R.string.language_selection_title) + } } override fun onPause() { super.onPause() - languageFilterListPreference.setSettingsFragment(null) + languageFilterList.setSettingsFragment(null) } - private fun loadSubtypes() { - val systemOnly = findPreference(Settings.PREF_USE_SYSTEM_LOCALES)!!.isChecked + private fun loadSubtypes(systemOnly: Boolean) { sortedSubtypes.clear() // list of all subtypes, any subtype added to sortedSubtypes will be removed to avoid duplicates val allSubtypes = getAllAvailableSubtypes().toMutableList() @@ -108,7 +133,7 @@ class LanguageSettingsFragment : SubScreenFragment() { allSubtypes.removeAll(enabledSubtypes) if (systemOnly) { // don't add anything else - languageFilterListPreference.setLanguages(sortedSubtypes.values, systemOnly) + languageFilterList.setLanguages(sortedSubtypes.values, systemOnly) return } @@ -133,7 +158,7 @@ class LanguageSettingsFragment : SubScreenFragment() { }.addToSortedSubtypes() // set languages - languageFilterListPreference.setLanguages(sortedSubtypes.values, systemOnly) + languageFilterList.setLanguages(sortedSubtypes.values, systemOnly) } private fun InputMethodSubtype.toSubtypeInfo(locale: Locale, isEnabled: Boolean = false) = diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFilterListPreference.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFilterList.kt similarity index 67% rename from app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFilterListPreference.kt rename to app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFilterList.kt index 83684b348..833565289 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFilterListPreference.kt +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFilterList.kt @@ -1,80 +1,40 @@ package org.dslul.openboard.inputmethod.latin.settings import android.content.Context -import android.graphics.Rect import android.graphics.Typeface -import android.os.Build import android.text.Spannable import android.text.SpannableString import android.text.SpannableStringBuilder import android.text.style.StyleSpan -import android.util.AttributeSet -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.* -import androidx.core.view.doOnLayout import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.widget.doAfterTextChanged -import androidx.preference.Preference -import androidx.preference.PreferenceGroupAdapter -import androidx.preference.PreferenceViewHolder import androidx.recyclerview.widget.RecyclerView import org.dslul.openboard.inputmethod.latin.R import org.dslul.openboard.inputmethod.latin.common.LocaleUtils -import org.dslul.openboard.inputmethod.latin.utils.* +import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils +import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils +import org.dslul.openboard.inputmethod.latin.utils.showMissingDictionaryDialog +import org.dslul.openboard.inputmethod.latin.utils.toLocale -class LanguageFilterListPreference(context: Context, attrs: AttributeSet) : Preference(context, attrs) { +class LanguageFilterListFakePreference(searchField: EditText, recyclerView: RecyclerView) { - private lateinit var preferenceView: View - private val adapter = LanguageAdapter(emptyList(), context) + private val adapter = LanguageAdapter(emptyList(), recyclerView.context) private val sortedSubtypes = mutableListOf>() - fun setSettingsFragment(newFragment: LanguageSettingsFragment?) { + fun setSettingsFragment(newFragment: LanguageFakeSettingsFragment?) { adapter.fragment = newFragment } - override fun onBindViewHolder(holder: PreferenceViewHolder) { - super.onBindViewHolder(holder) - preferenceView = holder.itemView -/* val a = holder.bindingAdapter as PreferenceGroupAdapter - preferenceManager.preferenceScreen -*/ - preferenceView.findViewById(R.id.language_list)?.adapter = adapter - val searchField = preferenceView.findViewById(R.id.search_field)!! + init { + recyclerView.adapter = adapter searchField.doAfterTextChanged { text -> adapter.list = sortedSubtypes.filter { it.first().displayName.startsWith(text.toString(), ignoreCase = true) } } - // todo: why the fuck isn't the recyclerview scrolling after switching to androidx? - // looks like nothing can scroll inside! - // maybe just make it a list and add a note to the changelog with request for help - // first play around with weirdly nested (Nested)ScrollViews and layouts - - val recycler = preferenceView.findViewById(R.id.language_list) -// recycler.isScrollContainer = true -// recycler.isNestedScrollingEnabled = true -// preferenceView.isScrollContainer = true -/* val windowFrame = Rect() - preferenceView.getWindowVisibleDisplayFrame(windowFrame) // rect the app has, we want the bottom (above screen bottom/navbar/keyboard) - val globalRect = Rect() - preferenceView.getGlobalVisibleRect(globalRect) // rect the view takes, we want the top (below the system language preference) - val newHeight = windowFrame.bottom - globalRect.top - preferenceView.findViewById(R.id.search_container).height - preferenceView.layoutParams = preferenceView.layoutParams.apply { height = newHeight -250 }*/ -/* preferenceView.doOnLayout { - // set correct height for recycler view, so there is no scrolling of the outside view happening - // not sure how, but probably this can also be achieved in xml... - val windowFrame = Rect() - it.getWindowVisibleDisplayFrame(windowFrame) // rect the app has, we want the bottom (above screen bottom/navbar/keyboard) - val globalRect = Rect() - it.getGlobalVisibleRect(globalRect) // rect the view takes, we want the top (below the system language preference) - val recycler = it.findViewById(R.id.language_list) - - val newHeight = windowFrame.bottom - globalRect.top - it.findViewById(R.id.search_container).height - if (newHeight != recycler.layoutParams.height) - recycler.layoutParams = recycler.layoutParams.apply { height = newHeight } - }*/ } fun setLanguages(list: Collection>, onlySystemLocales: Boolean) { @@ -90,7 +50,7 @@ class LanguageAdapter(list: List> = listOf(), context: RecyclerView.Adapter() { var onlySystemLocales = false private val prefs = DeviceProtectedUtils.getSharedPreferences(context) - var fragment: LanguageSettingsFragment? = null + var fragment: LanguageFakeSettingsFragment? = null var list: List> = list set(value) { diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsDialog.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsDialog.kt index 7e6db4144..447704499 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsDialog.kt +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsDialog.kt @@ -23,10 +23,10 @@ import java.util.* class LanguageSettingsDialog( context: Context, private val infos: MutableList, - private val fragment: LanguageSettingsFragment?, + private val fragment: LanguageFakeSettingsFragment?, private val onlySystemLocales: Boolean, private val onSubtypesChanged: () -> Unit -) : AlertDialog(context), LanguageSettingsFragment.Listener { +) : AlertDialog(context), LanguageFakeSettingsFragment.Listener { private val prefs = DeviceProtectedUtils.getSharedPreferences(context)!! private val view = LayoutInflater.from(context).inflate(R.layout.locale_settings_dialog, null) private val mainLocaleString = infos.first().subtype.locale diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsActivity.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsActivity.java index e6276095e..544009767 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsActivity.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsActivity.java @@ -52,6 +52,7 @@ public final class SettingsActivity extends AppCompatActivity final Intent i = getIntent(); if (Intent.ACTION_VIEW.equals(i.getAction()) && i.getData() != null) { new NewDictionaryAdder(this, null).addDictionary(i.getData(), null); + setIntent(new Intent()); // avoid opening again } getSupportFragmentManager().beginTransaction() .replace(android.R.id.content, new SettingsFragment()) diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SubScreenFragment.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SubScreenFragment.java index 56406063c..e4973624a 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SubScreenFragment.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SubScreenFragment.java @@ -140,7 +140,9 @@ public abstract class SubScreenFragment extends PreferenceFragmentCompat final Activity activity = getActivity(); if (activity instanceof AppCompatActivity) { final ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar(); - final CharSequence screenTitle = getPreferenceScreen().getTitle(); + final PreferenceScreen ps = getPreferenceScreen(); + if (ps == null) return; + final CharSequence screenTitle = ps.getTitle(); if (actionBar != null && screenTitle != null) { actionBar.setTitle(screenTitle); } diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/FragmentUtils.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/FragmentUtils.java index baa1fa1dc..71becb10a 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/FragmentUtils.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/FragmentUtils.java @@ -21,7 +21,7 @@ import org.dslul.openboard.inputmethod.latin.settings.AppearanceSettingsFragment import org.dslul.openboard.inputmethod.latin.settings.CorrectionSettingsFragment; import org.dslul.openboard.inputmethod.latin.settings.DebugSettingsFragment; import org.dslul.openboard.inputmethod.latin.settings.GestureSettingsFragment; -import org.dslul.openboard.inputmethod.latin.settings.LanguageSettingsFragment; +import org.dslul.openboard.inputmethod.latin.settings.LanguageFakeSettingsFragment; import org.dslul.openboard.inputmethod.latin.settings.PreferencesSettingsFragment; import org.dslul.openboard.inputmethod.latin.settings.SettingsFragment; import org.dslul.openboard.inputmethod.latin.settings.AboutFragment; @@ -49,7 +49,7 @@ public class FragmentUtils { sLatinImeFragments.add(UserDictionaryList.class.getName()); sLatinImeFragments.add(UserDictionaryLocalePicker.class.getName()); sLatinImeFragments.add(UserDictionarySettings.class.getName()); - sLatinImeFragments.add(LanguageSettingsFragment.class.getName()); + sLatinImeFragments.add(LanguageFakeSettingsFragment.class.getName()); } public static boolean isValidFragment(String fragmentName) { diff --git a/app/src/main/res/layout/language_fake_settings.xml b/app/src/main/res/layout/language_fake_settings.xml new file mode 100644 index 000000000..c92f07a17 --- /dev/null +++ b/app/src/main/res/layout/language_fake_settings.xml @@ -0,0 +1,20 @@ + + + + + diff --git a/app/src/main/res/layout/language_search_filter.xml b/app/src/main/res/layout/language_search_filter.xml index 3c2c44ea8..218ffba0f 100644 --- a/app/src/main/res/layout/language_search_filter.xml +++ b/app/src/main/res/layout/language_search_filter.xml @@ -4,7 +4,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="match_parent">