mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-06-06 14:50:14 +00:00
make SubtypeLocaleUtils less convoluted
still harder to understand than necessary...
This commit is contained in:
parent
69540b8d9f
commit
f72e8f41f4
5 changed files with 52 additions and 89 deletions
|
@ -14,7 +14,7 @@ import android.view.MotionEvent
|
||||||
import helium314.keyboard.accessibility.AccessibilityLongPressTimer.LongPressTimerCallback
|
import helium314.keyboard.accessibility.AccessibilityLongPressTimer.LongPressTimerCallback
|
||||||
import helium314.keyboard.keyboard.*
|
import helium314.keyboard.keyboard.*
|
||||||
import helium314.keyboard.latin.R
|
import helium314.keyboard.latin.R
|
||||||
import helium314.keyboard.latin.utils.SubtypeLocaleUtils
|
import helium314.keyboard.latin.utils.SubtypeLocaleUtils.displayName
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a delegate that can be registered in [MainKeyboardView] to enhance
|
* This class represents a delegate that can be registered in [MainKeyboardView] to enhance
|
||||||
|
@ -86,9 +86,7 @@ class MainKeyboardAccessibilityDelegate(
|
||||||
* @param keyboard The new keyboard.
|
* @param keyboard The new keyboard.
|
||||||
*/
|
*/
|
||||||
private fun announceKeyboardLanguage(keyboard: Keyboard) {
|
private fun announceKeyboardLanguage(keyboard: Keyboard) {
|
||||||
val languageText = SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(
|
sendWindowStateChanged(keyboard.mId.mSubtype.rawSubtype.displayName())
|
||||||
keyboard.mId.mSubtype.rawSubtype)
|
|
||||||
sendWindowStateChanged(languageText)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -96,7 +96,7 @@ public final class KeyboardLayoutSet {
|
||||||
public static void onSystemLocaleChanged() {
|
public static void onSystemLocaleChanged() {
|
||||||
clearKeyboardCache();
|
clearKeyboardCache();
|
||||||
LocaleKeyboardInfosKt.clearCache();
|
LocaleKeyboardInfosKt.clearCache();
|
||||||
SubtypeLocaleUtils.clearDisplayNameCache();
|
SubtypeLocaleUtils.clearSubtypeDisplayNameCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onKeyboardThemeChanged() {
|
public static void onKeyboardThemeChanged() {
|
||||||
|
|
|
@ -17,7 +17,6 @@ import helium314.keyboard.latin.utils.ScriptUtils
|
||||||
import helium314.keyboard.latin.utils.ScriptUtils.script
|
import helium314.keyboard.latin.utils.ScriptUtils.script
|
||||||
import helium314.keyboard.latin.utils.SubtypeLocaleUtils
|
import helium314.keyboard.latin.utils.SubtypeLocaleUtils
|
||||||
import helium314.keyboard.latin.utils.locale
|
import helium314.keyboard.latin.utils.locale
|
||||||
import helium314.keyboard.latin.utils.mainLayoutNameOrQwerty
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,21 +41,9 @@ class RichInputMethodSubtype private constructor(val rawSubtype: InputMethodSubt
|
||||||
|
|
||||||
val isCustom: Boolean get() = LayoutUtilsCustom.isCustomLayout(mainLayoutName)
|
val isCustom: Boolean get() = LayoutUtilsCustom.isCustomLayout(mainLayoutName)
|
||||||
|
|
||||||
val fullDisplayName: String get() {
|
val fullDisplayName: String get() = SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale)
|
||||||
if (isNoLanguage) {
|
|
||||||
return SubtypeLocaleUtils.getMainLayoutDisplayName(rawSubtype.mainLayoutNameOrQwerty())!!
|
|
||||||
}
|
|
||||||
return SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale)
|
|
||||||
}
|
|
||||||
|
|
||||||
val middleDisplayName: String
|
val middleDisplayName: String get() = SubtypeLocaleUtils.getSubtypeLanguageDisplayName(locale)
|
||||||
// Get the RichInputMethodSubtype's middle display name in its locale.
|
|
||||||
get() {
|
|
||||||
if (isNoLanguage) {
|
|
||||||
return SubtypeLocaleUtils.getMainLayoutDisplayName(rawSubtype.mainLayoutNameOrQwerty())!!
|
|
||||||
}
|
|
||||||
return SubtypeLocaleUtils.getSubtypeLanguageDisplayName(locale)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other !is RichInputMethodSubtype) return false
|
if (other !is RichInputMethodSubtype) return false
|
||||||
|
|
|
@ -40,7 +40,7 @@ object SubtypeLocaleUtils {
|
||||||
|
|
||||||
// Exceptional locale to subtype name with layout resource id map.
|
// Exceptional locale to subtype name with layout resource id map.
|
||||||
private val exceptionalLocaleToWithLayoutNameIds = HashMap<String, Int>()
|
private val exceptionalLocaleToWithLayoutNameIds = HashMap<String, Int>()
|
||||||
private val resourceSubtypeDisplayNames = HashMap<Int, String>()
|
private val resourceSubtypeDisplayNameCache = HashMap<Int, String>()
|
||||||
|
|
||||||
// Note that this initialization method can be called multiple times.
|
// Note that this initialization method can be called multiple times.
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -114,6 +114,7 @@ object SubtypeLocaleUtils {
|
||||||
return keyboardLayoutToNameIds[key] ?: UNKNOWN_KEYBOARD_LAYOUT
|
return keyboardLayoutToNameIds[key] ?: UNKNOWN_KEYBOARD_LAYOUT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Usually the [locale], but Locale.ROOT for exceptionalLocaleDisplayedInRootLocale, and system locale for NO_LANGUAGE */
|
||||||
private fun getDisplayLocaleOfSubtypeLocale(locale: Locale): Locale {
|
private fun getDisplayLocaleOfSubtypeLocale(locale: Locale): Locale {
|
||||||
val languageTag = locale.toLanguageTag()
|
val languageTag = locale.toLanguageTag()
|
||||||
if (languageTag == NO_LANGUAGE)
|
if (languageTag == NO_LANGUAGE)
|
||||||
|
@ -123,16 +124,13 @@ object SubtypeLocaleUtils {
|
||||||
return locale
|
return locale
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSubtypeLocaleDisplayNameInSystemLocale(locale: Locale): String {
|
/** Returns the full locale display name for use on space bar (considers exceptionalLocaleDisplayedInRootLocale) */
|
||||||
val displayLocale = resources.configuration.locale()
|
|
||||||
return getSubtypeLocaleDisplayNameInternal(locale, displayLocale)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSubtypeLocaleDisplayName(locale: Locale): String {
|
fun getSubtypeLocaleDisplayName(locale: Locale): String {
|
||||||
val displayLocale = getDisplayLocaleOfSubtypeLocale(locale)
|
val displayLocale = getDisplayLocaleOfSubtypeLocale(locale)
|
||||||
return getSubtypeLocaleDisplayNameInternal(locale, displayLocale)
|
return getSubtypeLocaleDisplayNameInternal(locale, displayLocale)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the language display name for use on space bar (considers exceptionalLocaleDisplayedInRootLocale) */
|
||||||
fun getSubtypeLanguageDisplayName(locale: Locale): String {
|
fun getSubtypeLanguageDisplayName(locale: Locale): String {
|
||||||
val languageLocale = if (exceptionalLocaleDisplayedInRootLocale.containsKey(locale.toLanguageTag()))
|
val languageLocale = if (exceptionalLocaleDisplayedInRootLocale.containsKey(locale.toLanguageTag()))
|
||||||
locale
|
locale
|
||||||
|
@ -141,15 +139,17 @@ object SubtypeLocaleUtils {
|
||||||
return getSubtypeLocaleDisplayNameInternal(languageLocale, getDisplayLocaleOfSubtypeLocale(locale))
|
return getSubtypeLocaleDisplayNameInternal(languageLocale, getDisplayLocaleOfSubtypeLocale(locale))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display name of subtype [locale] in [displayLocale].
|
||||||
|
* Considers exceptionalLocaleDisplayedInRootLocale and exceptionalLocaleToNameIds, defaults to Locale.localizedDisplayName.
|
||||||
|
*/
|
||||||
private fun getSubtypeLocaleDisplayNameInternal(locale: Locale, displayLocale: Locale): String {
|
private fun getSubtypeLocaleDisplayNameInternal(locale: Locale, displayLocale: Locale): String {
|
||||||
val languageTag = locale.toLanguageTag()
|
val languageTag = locale.toLanguageTag()
|
||||||
if (languageTag == NO_LANGUAGE) {
|
if (languageTag == NO_LANGUAGE) {
|
||||||
// "No language" subtype should be displayed in system locale.
|
// "No language" subtype should be displayed in system locale.
|
||||||
return resources.getString(R.string.subtype_no_language)
|
return resources.getString(R.string.subtype_no_language)
|
||||||
}
|
}
|
||||||
val exceptionalNameResId = if (displayLocale == Locale.ROOT
|
val exceptionalNameResId = if (displayLocale == Locale.ROOT && exceptionalLocaleDisplayedInRootLocale.containsKey(languageTag))
|
||||||
&& exceptionalLocaleDisplayedInRootLocale.containsKey(languageTag)
|
|
||||||
)
|
|
||||||
exceptionalLocaleDisplayedInRootLocale[languageTag]
|
exceptionalLocaleDisplayedInRootLocale[languageTag]
|
||||||
else
|
else
|
||||||
exceptionalLocaleToNameIds[languageTag]
|
exceptionalLocaleToNameIds[languageTag]
|
||||||
|
@ -161,51 +161,9 @@ object SubtypeLocaleUtils {
|
||||||
return StringUtils.capitalizeFirstCodePoint(displayName, displayLocale)
|
return StringUtils.capitalizeFirstCodePoint(displayName, displayLocale)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InputMethodSubtype's display name in its locale.
|
|
||||||
// isAdditionalSubtype (T=true, F=false)
|
|
||||||
// locale layout | display name
|
|
||||||
// ------ ------- - ----------------------
|
|
||||||
// en_US qwerty F English (US) exception
|
|
||||||
// en_GB qwerty F English (UK) exception
|
|
||||||
// es_US spanish F Español (EE.UU.) exception
|
|
||||||
// fr azerty F Français
|
|
||||||
// fr_CA qwerty F Français (Canada)
|
|
||||||
// fr_CH swiss F Français (Suisse)
|
|
||||||
// de qwertz F Deutsch
|
|
||||||
// de_CH swiss T Deutsch (Schweiz)
|
|
||||||
// zz qwerty F Alphabet (QWERTY) in system locale
|
|
||||||
// fr qwertz T Français (QWERTZ)
|
|
||||||
// de qwerty T Deutsch (QWERTY)
|
|
||||||
// en_US azerty T English (US) (AZERTY) exception
|
|
||||||
// zz azerty T Alphabet (AZERTY) in system locale
|
|
||||||
private fun getReplacementString(subtype: InputMethodSubtype, displayLocale: Locale): String =
|
|
||||||
subtype.getExtraValueOf(ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
|
|
||||||
?: getSubtypeLocaleDisplayNameInternal(subtype.locale(), displayLocale)
|
|
||||||
|
|
||||||
fun getDisplayNameInSystemLocale(mainLayoutName: String, locale: Locale): String {
|
|
||||||
getMainLayoutDisplayName(mainLayoutName)?.let { return it } // works for custom and latin layouts
|
|
||||||
|
|
||||||
// we have some locale-specific layout
|
|
||||||
for (subtype in SubtypeSettings.getResourceSubtypesForLocale(locale)) {
|
|
||||||
if (mainLayoutName == getMainLayoutFromExtraValue(subtype.extraValue))
|
|
||||||
return getSubtypeDisplayNameInSystemLocale(subtype)
|
|
||||||
}
|
|
||||||
return mainLayoutName // should never happen...
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSubtypeDisplayNameInSystemLocale(subtype: InputMethodSubtype): String {
|
|
||||||
resourceSubtypeDisplayNames[subtype.hashCode()]?.let { return it }
|
|
||||||
|
|
||||||
val displayName = getSubtypeDisplayNameInternal(subtype, resources.configuration.locale())
|
|
||||||
if (!subtype.containsExtraValueKey(ExtraValue.IS_ADDITIONAL_SUBTYPE)) {
|
|
||||||
resourceSubtypeDisplayNames[subtype.hashCode()] = displayName
|
|
||||||
}
|
|
||||||
return displayName
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun clearDisplayNameCache() {
|
fun clearSubtypeDisplayNameCache() {
|
||||||
resourceSubtypeDisplayNames.clear()
|
resourceSubtypeDisplayNameCache.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -216,27 +174,48 @@ object SubtypeLocaleUtils {
|
||||||
return subtype.locale().toString() + "/" + subtype.mainLayoutNameOrQwerty()
|
return subtype.locale().toString() + "/" + subtype.mainLayoutNameOrQwerty()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSubtypeDisplayNameInternal(subtype: InputMethodSubtype, displayLocale: Locale): String {
|
/** Subtype display name is <Locale> (<Layout>), defaults to system locale */
|
||||||
val replacementString = getReplacementString(subtype, displayLocale)
|
fun InputMethodSubtype.displayName(displayLocale: Locale? = null): String {
|
||||||
return runInLocale(resources, displayLocale) { res: Resources ->
|
if (displayLocale == null) resourceSubtypeDisplayNameCache[hashCode()]?.let { return it }
|
||||||
try {
|
|
||||||
StringUtils.capitalizeFirstCodePoint(res.getString(subtype.nameResId, replacementString), displayLocale)
|
val layoutName = mainLayoutName()
|
||||||
} catch (e: Resources.NotFoundException) {
|
if (layoutName != null && LayoutUtilsCustom.isCustomLayout(layoutName)) {
|
||||||
Log.w(TAG, ("Unknown subtype: mode=${subtype.mode} nameResId=${subtype.nameResId} locale=${subtype.locale()} extra=${subtype.extraValue}\n${DebugLogUtils.getStackTrace()}"))
|
return resources.getString(
|
||||||
""
|
R.string.subtype_with_layout_generic,
|
||||||
}
|
locale().localizedDisplayName(resources, displayLocale),
|
||||||
|
LayoutUtilsCustom.getDisplayName(layoutName)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val actualDisplayLocale = displayLocale ?: resources.configuration.locale()
|
||||||
|
// replacement for %s in nameResId
|
||||||
|
// this is usually the locale, but can also include a subtype name when subtype_generic is used
|
||||||
|
val replacementString = getExtraValueOf(ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
|
||||||
|
?: getSubtypeLocaleDisplayNameInternal(locale(), actualDisplayLocale)
|
||||||
|
|
||||||
|
val name = runCatching {
|
||||||
|
if (displayLocale == null) resources.getString(nameResId, replacementString)
|
||||||
|
else runInLocale(resources, displayLocale) { resources.getString(nameResId, replacementString) }
|
||||||
|
}.getOrNull() ?: locale().localizedDisplayName(resources, displayLocale)
|
||||||
|
val displayName = StringUtils.capitalizeFirstCodePoint(name, actualDisplayLocale)
|
||||||
|
if (displayLocale == null && !containsExtraValueKey(ExtraValue.IS_ADDITIONAL_SUBTYPE))
|
||||||
|
resourceSubtypeDisplayNameCache[hashCode()] = displayName
|
||||||
|
return displayName
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMainLayoutDisplayName(layoutName: String): String? =
|
fun getMainLayoutDisplayName(layoutName: String): String? =
|
||||||
if (LayoutUtilsCustom.isCustomLayout(layoutName)) LayoutUtilsCustom.getDisplayName(layoutName)
|
if (LayoutUtilsCustom.isCustomLayout(layoutName)) LayoutUtilsCustom.getDisplayName(layoutName)
|
||||||
else keyboardLayoutToDisplayName[layoutName]
|
else keyboardLayoutToDisplayName[layoutName]
|
||||||
|
|
||||||
fun InputMethodSubtype.displayName(): String {
|
fun getLayoutDisplayNameInSystemLocale(mainLayoutName: String, locale: Locale): String {
|
||||||
val layoutName = mainLayoutNameOrQwerty()
|
getMainLayoutDisplayName(mainLayoutName)?.let { return it } // works for custom and latin layouts
|
||||||
if (LayoutUtilsCustom.isCustomLayout(layoutName))
|
|
||||||
return "${locale().localizedDisplayName(resources)} (${LayoutUtilsCustom.getDisplayName(layoutName)})"
|
// we have some locale-specific layout, use the subtype name
|
||||||
return getSubtypeDisplayNameInSystemLocale(this)
|
for (subtype in SubtypeSettings.getResourceSubtypesForLocale(locale)) {
|
||||||
|
if (mainLayoutName == getMainLayoutFromExtraValue(subtype.extraValue))
|
||||||
|
return subtype.displayName()
|
||||||
|
}
|
||||||
|
return mainLayoutName // should never happen...
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -248,7 +227,6 @@ object SubtypeLocaleUtils {
|
||||||
const val EMOJI = "emoji"
|
const val EMOJI = "emoji"
|
||||||
val UNKNOWN_KEYBOARD_LAYOUT = R.string.subtype_generic
|
val UNKNOWN_KEYBOARD_LAYOUT = R.string.subtype_generic
|
||||||
|
|
||||||
private val TAG = SubtypeLocaleUtils::class.java.simpleName
|
|
||||||
private const val SUBTYPE_NAME_RESOURCE_PREFIX = "string/subtype_"
|
private const val SUBTYPE_NAME_RESOURCE_PREFIX = "string/subtype_"
|
||||||
private const val SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX = "string/subtype_generic_"
|
private const val SUBTYPE_NAME_RESOURCE_GENERIC_PREFIX = "string/subtype_generic_"
|
||||||
private const val SUBTYPE_NAME_RESOURCE_WITH_LAYOUT_PREFIX = "string/subtype_with_layout_"
|
private const val SUBTYPE_NAME_RESOURCE_WITH_LAYOUT_PREFIX = "string/subtype_with_layout_"
|
||||||
|
|
|
@ -407,7 +407,7 @@ private fun MainLayoutRow(
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
modifier = Modifier.widthIn(min = 200.dp).fillMaxWidth()
|
modifier = Modifier.widthIn(min = 200.dp).fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Text(SubtypeLocaleUtils.getDisplayNameInSystemLocale(it, currentSubtype.locale))
|
Text(SubtypeLocaleUtils.getLayoutDisplayNameInSystemLocale(it, currentSubtype.locale))
|
||||||
Row (verticalAlignment = Alignment.CenterVertically) {
|
Row (verticalAlignment = Alignment.CenterVertically) {
|
||||||
IconButton({ showLayoutEditDialog = it to null }) { Icon(painterResource(R.drawable.ic_edit), stringResource(R.string.edit_layout)) }
|
IconButton({ showLayoutEditDialog = it to null }) { Icon(painterResource(R.drawable.ic_edit), stringResource(R.string.edit_layout)) }
|
||||||
if (it in customLayouts)
|
if (it in customLayouts)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue