From 452770566c1b6c5ec04ba9139d153dd038b49f79 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Mon, 31 Mar 2025 16:31:52 +0200 Subject: [PATCH] avoid creating additional subtypes that are the same as a resource subtype --- .../keyboard/latin/settings/SettingsSubtype.kt | 4 ++++ .../keyboard/latin/utils/SubtypeSettings.kt | 17 +++++++++++++++-- .../latin/utils/SubtypeUtilsAdditional.kt | 2 +- .../keyboard/settings/screens/SubtypeScreen.kt | 9 +++++++-- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/latin/settings/SettingsSubtype.kt b/app/src/main/java/helium314/keyboard/latin/settings/SettingsSubtype.kt index ca18b7fd..b966d92d 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/SettingsSubtype.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/SettingsSubtype.kt @@ -14,11 +14,13 @@ import helium314.keyboard.latin.utils.LayoutType.Companion.toExtraValue import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.ScriptUtils import helium314.keyboard.latin.utils.ScriptUtils.script +import helium314.keyboard.latin.utils.SubtypeSettings import helium314.keyboard.latin.utils.SubtypeUtilsAdditional import helium314.keyboard.latin.utils.locale import java.util.Locale // some kind of intermediate between the string stored in preferences and an InputMethodSubtype +// todo: consider using a hashMap or sortedMap instead of a string if we run into comparison issues once again data class SettingsSubtype(val locale: Locale, val extraValues: String) { fun toPref() = locale.toLanguageTag() + Separators.SET + extraValues @@ -70,6 +72,8 @@ data class SettingsSubtype(val locale: Locale, val extraValues: String) { prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!! .split(Separators.SETS).contains(toPref()) + fun isSameAsDefault() = SubtypeSettings.getResourceSubtypesForLocale(locale).any { it.toSettingsSubtype() == this.toPref().toSettingsSubtype() } + companion object { fun String.toSettingsSubtype(): SettingsSubtype = SettingsSubtype( diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt index f533223e..757ff2fa 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt @@ -124,6 +124,10 @@ object SubtypeSettings { fun getAvailableSubtypeLocales(): List = resourceSubtypesByLocale.keys.toList() + /** + * Update subtypes that contain the layout. If new name is null (layout deleted) and the + * subtype is now identical to a resource subtype, remove the subtype from additional subtypes. + */ fun onRenameLayout(type: LayoutType, from: String, to: String?, context: Context) { val prefs = context.prefs() listOf( @@ -131,10 +135,19 @@ object SubtypeSettings { Settings.PREF_ENABLED_SUBTYPES to Defaults.PREF_ENABLED_SUBTYPES, Settings.PREF_SELECTED_SUBTYPE to Defaults.PREF_SELECTED_SUBTYPE ).forEach { (key, default) -> - val new = prefs.getString(key, default)!!.split(Separators.SETS).mapTo(mutableSetOf()) { + val new = prefs.getString(key, default)!!.split(Separators.SETS).mapNotNullTo(mutableSetOf()) { val subtype = it.toSettingsSubtype() if (subtype.layoutName(type) == from) { - if (to == null) subtype.withoutLayout(type).toPref() + if (to == null) { + val defaultLayout = if (type !== LayoutType.MAIN) null + // if we just delete a main layout, we may end up with something like Hindi (QWERTY) + // so better replace it with a default layout for that locale + else resourceSubtypesByLocale[subtype.locale]?.first()?.mainLayoutName() + val newSubtype = if (defaultLayout == null) subtype.withoutLayout(type) + else subtype.withLayout(type, defaultLayout) + if (newSubtype.isSameAsDefault() && key == Settings.PREF_ADDITIONAL_SUBTYPES) null + else subtype.withoutLayout(type).toPref() + } else subtype.withLayout(type, to).toPref() } else subtype.toPref() diff --git a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtilsAdditional.kt b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtilsAdditional.kt index b9bce10a..95875bac 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtilsAdditional.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/SubtypeUtilsAdditional.kt @@ -70,7 +70,7 @@ object SubtypeUtilsAdditional { val additionalSubtypes = SubtypeSettings.createSettingsSubtypes(prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!!) .toMutableList() additionalSubtypes.remove(from) - if (SubtypeSettings.getResourceSubtypesForLocale(to.locale).none { it.toSettingsSubtype() == to }) { + if (!to.isSameAsDefault()) { // We only add the "to" subtype if it's not equal to a resource subtype. // This means we make additional subtype disappear as magically as it was added if all settings are default. // If we don't do this, enabling the base subtype will result in the additional subtype being enabled, diff --git a/app/src/main/java/helium314/keyboard/settings/screens/SubtypeScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/SubtypeScreen.kt index a06ab1e2..4a96d73f 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/SubtypeScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/SubtypeScreen.kt @@ -388,8 +388,13 @@ private fun MainLayoutRow( title = { Text(stringResource(R.string.delete_layout, LayoutUtilsCustom.getDisplayName(it))) }, content = { if (others) Text(stringResource(R.string.layout_in_use)) }, onConfirmed = { - if (it == currentSubtype.mainLayoutName()) - setCurrentSubtype(currentSubtype.withoutLayout(LayoutType.MAIN)) + if (it == currentSubtype.mainLayoutName()) { + // similar to what is done in SubtypeSettings.onRenameLayout + val defaultLayout = SubtypeSettings.getResourceSubtypesForLocale(currentSubtype.locale).firstOrNull()?.mainLayoutName() + val newSubtype = if (defaultLayout == null) currentSubtype.withoutLayout(LayoutType.MAIN) + else currentSubtype.withLayout(LayoutType.MAIN, defaultLayout) + setCurrentSubtype(newSubtype) + } LayoutUtilsCustom.deleteLayout(it, LayoutType.MAIN, ctx) (ctx.getActivity() as? SettingsActivity)?.prefChanged() }