(partially) remove workaround for key params

This commit is contained in:
Helium314 2024-05-18 10:30:46 +02:00
parent 5b4ba11fb7
commit 2466187eb3
4 changed files with 168 additions and 168 deletions

View file

@ -4,13 +4,9 @@ package helium314.keyboard.keyboard.internal.keyboard_parser
import android.content.Context
import android.content.res.Configuration
import helium314.keyboard.latin.utils.Log
import android.view.inputmethod.EditorInfo
import androidx.annotation.StringRes
import helium314.keyboard.keyboard.Key
import helium314.keyboard.keyboard.Key.KeyParams
import helium314.keyboard.keyboard.KeyboardId
import helium314.keyboard.keyboard.KeyboardTheme
import helium314.keyboard.keyboard.internal.KeyboardIconsSet
import helium314.keyboard.keyboard.internal.KeyboardParams
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyData
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyLabel
@ -18,20 +14,15 @@ import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyType
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.SimplePopups
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.TextKeyData
import helium314.keyboard.latin.R
import helium314.keyboard.latin.common.Constants
import helium314.keyboard.latin.common.LocaleUtils.constructLocale
import helium314.keyboard.latin.common.isEmoji
import helium314.keyboard.latin.define.DebugFlags
import helium314.keyboard.latin.settings.Settings
import helium314.keyboard.latin.spellcheck.AndroidSpellCheckerService
import helium314.keyboard.latin.utils.InputTypeUtils
import helium314.keyboard.latin.utils.POPUP_KEYS_LAYOUT
import helium314.keyboard.latin.utils.POPUP_KEYS_NUMBER
import helium314.keyboard.latin.utils.ScriptUtils
import helium314.keyboard.latin.utils.ScriptUtils.script
import helium314.keyboard.latin.utils.removeFirst
import helium314.keyboard.latin.utils.replaceFirst
import helium314.keyboard.latin.utils.runInLocale
import helium314.keyboard.latin.utils.splitAt
import helium314.keyboard.latin.utils.sumOf
@ -277,31 +268,12 @@ class KeyboardParser(private val params: KeyboardParams, private val context: Co
return functionalKeysLeft to functionalKeysRight
}
// this is not nice in here, but otherwise we'd need context, and defaultLabelFlags and infos for toKeyParams
// improve it later, but currently this messy way is still ok
// todo: try moving defaultLabelFlags and layoutInfo into KeyboardParams
private fun KeyData.processFunctionalKeys(): KeyData? = when (label) {
// todo: why defaultLabelFlags exactly here? is this for armenian or bengali period labels? try removing also check in holo theme
KeyLabel.PERIOD -> copy(newLabelFlags = labelFlags or defaultLabelFlags)
KeyLabel.SHIFT -> if (infos.hasShiftKey) this else null
KeyLabel.ACTION -> copy(
// todo: evaluating the label should actually only happen in toKeyParams
// this label change already makes it necessary to provide the background in here too, because toKeyParams can't use action as label
newLabel = "${getActionKeyLabel()}|${getActionKeyCode()}",
newPopup = popup.merge(getActionKeyPopupKeys()?.let { SimplePopups(it) }),
// the label change is messing with toKeyParams, so we need to supply the appropriate BG type here
newType = type ?: KeyType.ENTER_EDITING,
newLabelFlags = Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_AUTO_X_SCALE or
Key.LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR or
Key.LABEL_FLAGS_HAS_POPUP_HINT or KeyboardTheme.getThemeActionAndEmojiKeyLabelFlags(params.mThemeId)
)
else -> {
// this is ugly...
if (label.length > 8 && label.startsWith("!string/")) {
val id = context.resources.getIdentifier(label.substringAfter("!string/"), "string", context.packageName)
if (id != 0) copy(newLabel = getInLocale(id))
else this
} else this
}
else -> this
}
private fun addNumberRowOrPopupKeys(baseKeys: MutableList<MutableList<KeyData>>) {
@ -340,122 +312,6 @@ class KeyboardParser(private val params: KeyboardParams, private val context: Co
}
}
private fun getActionKeyLabel(): String {
if (params.mId.isMultiLine && (params.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED || params.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED))
return "!icon/enter_key"
val iconName = when (params.mId.imeAction()) {
EditorInfo.IME_ACTION_GO -> KeyboardIconsSet.NAME_GO_KEY
EditorInfo.IME_ACTION_SEARCH -> KeyboardIconsSet.NAME_SEARCH_KEY
EditorInfo.IME_ACTION_SEND -> KeyboardIconsSet.NAME_SEND_KEY
EditorInfo.IME_ACTION_NEXT -> KeyboardIconsSet.NAME_NEXT_KEY
EditorInfo.IME_ACTION_DONE -> KeyboardIconsSet.NAME_DONE_KEY
EditorInfo.IME_ACTION_PREVIOUS -> KeyboardIconsSet.NAME_PREVIOUS_KEY
InputTypeUtils.IME_ACTION_CUSTOM_LABEL -> return params.mId.mCustomActionLabel
else -> return "!icon/enter_key"
}
val replacement = iconName.replaceIconWithLabelIfNoDrawable()
return if (iconName == replacement) // i.e. icon exists
"!icon/$iconName"
else
replacement
}
private fun getActionKeyCode() =
if (params.mId.isMultiLine && (params.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED || params.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED))
"!code/key_shift_enter"
else "!code/key_enter"
private fun getActionKeyPopupKeys(): Collection<String>? {
val action = params.mId.imeAction()
val navigatePrev = params.mId.navigatePrevious()
val navigateNext = params.mId.navigateNext()
return when {
params.mId.passwordInput() -> when {
navigatePrev && action == EditorInfo.IME_ACTION_NEXT -> createPopupKeys(POPUP_EYS_NAVIGATE_PREVIOUS)
action == EditorInfo.IME_ACTION_NEXT -> null
navigateNext && action == EditorInfo.IME_ACTION_PREVIOUS -> createPopupKeys(POPUP_EYS_NAVIGATE_NEXT)
action == EditorInfo.IME_ACTION_PREVIOUS -> null
navigateNext && navigatePrev -> createPopupKeys(POPUP_EYS_NAVIGATE_PREVIOUS_NEXT)
navigateNext -> createPopupKeys(POPUP_EYS_NAVIGATE_NEXT)
navigatePrev -> createPopupKeys(POPUP_EYS_NAVIGATE_PREVIOUS)
else -> null
}
// could change definition of numbers to query a range, or have a pre-defined list, but not that crucial
params.mId.isNumberLayout || params.mId.mMode in listOf(KeyboardId.MODE_EMAIL, KeyboardId.MODE_DATE, KeyboardId.MODE_TIME, KeyboardId.MODE_DATETIME) -> when {
action == EditorInfo.IME_ACTION_NEXT && navigatePrev -> createPopupKeys(POPUP_EYS_NAVIGATE_PREVIOUS)
action == EditorInfo.IME_ACTION_NEXT -> null
action == EditorInfo.IME_ACTION_PREVIOUS && navigateNext -> createPopupKeys(POPUP_EYS_NAVIGATE_NEXT)
action == EditorInfo.IME_ACTION_PREVIOUS -> null
navigateNext && navigatePrev -> createPopupKeys(POPUP_EYS_NAVIGATE_PREVIOUS_NEXT)
navigateNext -> createPopupKeys(POPUP_EYS_NAVIGATE_NEXT)
navigatePrev -> createPopupKeys(POPUP_EYS_NAVIGATE_PREVIOUS)
else -> null
}
action == EditorInfo.IME_ACTION_NEXT && navigatePrev -> createPopupKeys(POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS)
action == EditorInfo.IME_ACTION_NEXT -> createPopupKeys(POPUP_EYS_NAVIGATE_EMOJI)
action == EditorInfo.IME_ACTION_PREVIOUS && navigateNext -> createPopupKeys(POPUP_EYS_NAVIGATE_EMOJI_NEXT)
action == EditorInfo.IME_ACTION_PREVIOUS -> createPopupKeys(POPUP_EYS_NAVIGATE_EMOJI)
navigateNext && navigatePrev -> createPopupKeys(POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS_NEXT)
navigateNext -> createPopupKeys(POPUP_EYS_NAVIGATE_EMOJI_NEXT)
navigatePrev -> createPopupKeys(POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS)
else -> createPopupKeys(POPUP_EYS_NAVIGATE_EMOJI)
}
}
private fun createPopupKeys(popupKeysDef: String): List<String> {
val popupKeys = mutableListOf<String>()
for (popupKey in popupKeysDef.split(",")) {
val iconPrefixRemoved = popupKey.substringAfter("!icon/")
if (iconPrefixRemoved == popupKey) { // i.e. there is no !icon/
popupKeys.add(popupKey)
continue
}
val iconName = iconPrefixRemoved.substringBefore("|")
val replacementText = iconName.replaceIconWithLabelIfNoDrawable()
if (replacementText == iconName) { // i.e. we have the drawable
popupKeys.add(popupKey)
} else {
popupKeys.add(Key.POPUP_KEYS_HAS_LABELS)
popupKeys.add("$replacementText|${iconPrefixRemoved.substringAfter("|")}")
}
}
// remove emoji shortcut on enter in tablet mode (like original, because bottom row always has an emoji key)
// (probably not necessary, but whatever)
if (Settings.getInstance().isTablet && popupKeys.remove("!icon/emoji_action_key|!code/key_emoji")) {
val i = popupKeys.indexOfFirst { it.startsWith(Key.POPUP_KEYS_FIXED_COLUMN_ORDER) }
if (i > -1) {
val n = popupKeys[i].substringAfter(Key.POPUP_KEYS_FIXED_COLUMN_ORDER).toIntOrNull()
if (n != null)
popupKeys[i] = popupKeys[i].replace(n.toString(), (n - 1).toString())
}
}
return popupKeys
}
private fun String.replaceIconWithLabelIfNoDrawable(): String {
if (params.mIconsSet.getIconDrawable(this) != null) return this
if (params.mId.mWidth == AndroidSpellCheckerService.SPELLCHECKER_DUMMY_KEYBOARD_WIDTH
&& params.mId.mHeight == AndroidSpellCheckerService.SPELLCHECKER_DUMMY_KEYBOARD_HEIGHT
&& !params.mId.mSubtype.hasExtraValue(Constants.Subtype.ExtraValue.EMOJI_CAPABLE)
)
// fake keyboard that is used by spell checker (for key coordinates), but not shown to the user
// often this doesn't have any icons loaded, and there is no need to bother with this
return this
val id = context.resources.getIdentifier("label_$this", "string", context.packageName)
if (id == 0) {
Log.w(TAG, "no resource for label $this in ${params.mId}")
return this
}
return getInLocale(id)
}
private fun getInLocale(@StringRes id: Int): String {
// todo: hi-Latn strings instead of this workaround?
val locale = if (params.mId.locale.toLanguageTag() == "hi-Latn") "en_IN".constructLocale()
else params.mId.locale
return runInLocale(context, locale) { it.getString(id) }
}
companion object {
private const val TAG = "KeyboardParser"
@ -526,15 +382,6 @@ fun String.rtlLabel(params: KeyboardParams): String {
}
}
// could make arrays right away, but they need to be copied anyway as popupKeys arrays are modified when creating KeyParams
private const val POPUP_EYS_NAVIGATE_PREVIOUS = "!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard"
private const val POPUP_EYS_NAVIGATE_NEXT = "!icon/clipboard_action_key|!code/key_clipboard,!icon/next_key|!code/key_action_next"
private const val POPUP_EYS_NAVIGATE_PREVIOUS_NEXT = "!fixedColumnOrder!3,!needsDividers!,!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard,!icon/next_key|!code/key_action_next"
private const val POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS = "!fixedColumnOrder!3,!needsDividers!,!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji"
private const val POPUP_EYS_NAVIGATE_EMOJI = "!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji"
private const val POPUP_EYS_NAVIGATE_EMOJI_NEXT = "!fixedColumnOrder!3,!needsDividers!,!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji,!icon/next_key|!code/key_action_next"
private const val POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS_NEXT = "!fixedColumnOrder!4,!needsDividers!,!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji,!icon/next_key|!code/key_action_next"
const val LAYOUT_SYMBOLS = "symbols"
const val LAYOUT_SYMBOLS_SHIFTED = "symbols_shifted"
const val LAYOUT_SYMBOLS_ARABIC = "symbols_arabic"

View file

@ -5,6 +5,7 @@
*/
package helium314.keyboard.keyboard.internal.keyboard_parser.floris
import android.view.inputmethod.EditorInfo
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
@ -17,8 +18,12 @@ import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode.check
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyLabel.convertFlorisLabel
import helium314.keyboard.keyboard.internal.keyboard_parser.rtlLabel
import helium314.keyboard.latin.common.Constants
import helium314.keyboard.latin.common.LocaleUtils.constructLocale
import helium314.keyboard.latin.common.StringUtils
import helium314.keyboard.latin.settings.Settings
import helium314.keyboard.latin.spellcheck.AndroidSpellCheckerService
import helium314.keyboard.latin.utils.InputTypeUtils
import helium314.keyboard.latin.utils.Log
// taken from FlorisBoard, small modifications (see also KeyData)
// internal keys removed (currently no plan to support them)
@ -84,6 +89,7 @@ sealed interface KeyData : AbstractKeyData {
KeyboardId.ELEMENT_SYMBOLS -> params.mLocaleKeyboardInfos.getShiftSymbolLabel(Settings.getInstance().isTablet)
KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED, KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED,
KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED, KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED -> "!icon/${KeyboardIconsSet.NAME_SHIFT_KEY_SHIFTED}"
else -> "!icon/${KeyboardIconsSet.NAME_SHIFT_KEY}"
}
@ -138,6 +144,144 @@ sealed interface KeyData : AbstractKeyData {
}
return popupKeys
}
private fun String.resolveStringLabel(params: KeyboardParams): String {
if (length < 9 || !startsWith("!string/")) return this
val id = Settings.getInstance().getStringResIdByName(substringAfter("!string/"))
if (id == 0) return this
return getStringInLocale(id, params)
}
private fun getStringInLocale(id: Int, params: KeyboardParams): String {
// todo: hi-Latn strings instead of this workaround?
val locale = if (params.mId.locale.toLanguageTag() == "hi-Latn") "en_IN".constructLocale()
else params.mId.locale
return Settings.getInstance().getInLocale(id, locale)
}
// action key stuff below
// todo (later): should this be handled with metaState? but metaState shift would require LOTS of changes...
private fun getActionKeyCode(params: KeyboardParams) =
if (params.mId.isMultiLine && (params.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED || params.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED))
"!code/key_shift_enter"
else "!code/key_enter"
private fun getActionKeyLabel(params: KeyboardParams): String {
if (params.mId.isMultiLine && (params.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED || params.mId.mElementId == KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED))
return "!icon/enter_key"
val iconName = when (params.mId.imeAction()) {
EditorInfo.IME_ACTION_GO -> KeyboardIconsSet.NAME_GO_KEY
EditorInfo.IME_ACTION_SEARCH -> KeyboardIconsSet.NAME_SEARCH_KEY
EditorInfo.IME_ACTION_SEND -> KeyboardIconsSet.NAME_SEND_KEY
EditorInfo.IME_ACTION_NEXT -> KeyboardIconsSet.NAME_NEXT_KEY
EditorInfo.IME_ACTION_DONE -> KeyboardIconsSet.NAME_DONE_KEY
EditorInfo.IME_ACTION_PREVIOUS -> KeyboardIconsSet.NAME_PREVIOUS_KEY
InputTypeUtils.IME_ACTION_CUSTOM_LABEL -> return params.mId.mCustomActionLabel
else -> return "!icon/enter_key"
}
val replacement = iconName.replaceIconWithLabelIfNoDrawable(params)
return if (iconName == replacement) // i.e. icon exists
"!icon/$iconName"
else
replacement
}
private fun getActionKeyPopupKeys(params: KeyboardParams): SimplePopups? =
getActionKeyPopupKeyString(params.mId)?.let { createActionPopupKeys(it, params) }
private fun getActionKeyPopupKeyString(keyboardId: KeyboardId): String? {
val action = keyboardId.imeAction()
val navigatePrev = keyboardId.navigatePrevious()
val navigateNext = keyboardId.navigateNext()
return when {
keyboardId.passwordInput() -> when {
navigatePrev && action == EditorInfo.IME_ACTION_NEXT -> POPUP_EYS_NAVIGATE_PREVIOUS
action == EditorInfo.IME_ACTION_NEXT -> null
navigateNext && action == EditorInfo.IME_ACTION_PREVIOUS -> POPUP_EYS_NAVIGATE_NEXT
action == EditorInfo.IME_ACTION_PREVIOUS -> null
navigateNext && navigatePrev -> POPUP_EYS_NAVIGATE_PREVIOUS_NEXT
navigateNext -> POPUP_EYS_NAVIGATE_NEXT
navigatePrev -> POPUP_EYS_NAVIGATE_PREVIOUS
else -> null
}
// could change definition of numbers to query a range, or have a pre-defined list, but not that crucial
keyboardId.isNumberLayout || keyboardId.mMode in listOf(KeyboardId.MODE_EMAIL, KeyboardId.MODE_DATE, KeyboardId.MODE_TIME, KeyboardId.MODE_DATETIME) -> when {
action == EditorInfo.IME_ACTION_NEXT && navigatePrev -> POPUP_EYS_NAVIGATE_PREVIOUS
action == EditorInfo.IME_ACTION_NEXT -> null
action == EditorInfo.IME_ACTION_PREVIOUS && navigateNext -> POPUP_EYS_NAVIGATE_NEXT
action == EditorInfo.IME_ACTION_PREVIOUS -> null
navigateNext && navigatePrev -> POPUP_EYS_NAVIGATE_PREVIOUS_NEXT
navigateNext -> POPUP_EYS_NAVIGATE_NEXT
navigatePrev -> POPUP_EYS_NAVIGATE_PREVIOUS
else -> null
}
action == EditorInfo.IME_ACTION_NEXT && navigatePrev -> POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS
action == EditorInfo.IME_ACTION_NEXT -> POPUP_EYS_NAVIGATE_EMOJI
action == EditorInfo.IME_ACTION_PREVIOUS && navigateNext -> POPUP_EYS_NAVIGATE_EMOJI_NEXT
action == EditorInfo.IME_ACTION_PREVIOUS -> POPUP_EYS_NAVIGATE_EMOJI
navigateNext && navigatePrev -> POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS_NEXT
navigateNext -> POPUP_EYS_NAVIGATE_EMOJI_NEXT
navigatePrev -> POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS
else -> POPUP_EYS_NAVIGATE_EMOJI
}
}
private fun createActionPopupKeys(popupKeysDef: String, params: KeyboardParams): SimplePopups {
val popupKeys = mutableListOf<String>()
for (popupKey in popupKeysDef.split(",")) {
val iconPrefixRemoved = popupKey.substringAfter("!icon/")
if (iconPrefixRemoved == popupKey) { // i.e. there is no !icon/
popupKeys.add(popupKey)
continue
}
val iconName = iconPrefixRemoved.substringBefore("|")
val replacementText = iconName.replaceIconWithLabelIfNoDrawable(params)
if (replacementText == iconName) { // i.e. we have the drawable
popupKeys.add(popupKey)
} else {
popupKeys.add(Key.POPUP_KEYS_HAS_LABELS)
popupKeys.add("$replacementText|${iconPrefixRemoved.substringAfter("|")}")
}
}
// remove emoji shortcut on enter in tablet mode (like original, because bottom row always has an emoji key)
// (probably not necessary, but whatever)
if (Settings.getInstance().isTablet && popupKeys.remove("!icon/emoji_action_key|!code/key_emoji")) {
val i = popupKeys.indexOfFirst { it.startsWith(Key.POPUP_KEYS_FIXED_COLUMN_ORDER) }
if (i > -1) {
val n = popupKeys[i].substringAfter(Key.POPUP_KEYS_FIXED_COLUMN_ORDER).toIntOrNull()
if (n != null)
popupKeys[i] = popupKeys[i].replace(n.toString(), (n - 1).toString())
}
}
return SimplePopups(popupKeys)
}
private fun String.replaceIconWithLabelIfNoDrawable(params: KeyboardParams): String {
if (params.mIconsSet.getIconDrawable(this) != null) return this
if (params.mId.mWidth == AndroidSpellCheckerService.SPELLCHECKER_DUMMY_KEYBOARD_WIDTH
&& params.mId.mHeight == AndroidSpellCheckerService.SPELLCHECKER_DUMMY_KEYBOARD_HEIGHT
&& !params.mId.mSubtype.hasExtraValue(Constants.Subtype.ExtraValue.EMOJI_CAPABLE)
)
// fake keyboard that is used by spell checker (for key coordinates), but not shown to the user
// often this doesn't have any icons loaded, and there is no need to bother with this
return this
val id = Settings.getInstance().getStringResIdByName("label_$this")
if (id == 0) {
Log.w("TextKeyData", "no resource for label $this in ${params.mId}")
return this
}
return getStringInLocale(id, params)
}
// could make arrays right away, but they need to be copied anyway as popupKeys arrays are modified when creating KeyParams
private const val POPUP_EYS_NAVIGATE_PREVIOUS = "!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard"
private const val POPUP_EYS_NAVIGATE_NEXT = "!icon/clipboard_action_key|!code/key_clipboard,!icon/next_key|!code/key_action_next"
private const val POPUP_EYS_NAVIGATE_PREVIOUS_NEXT = "!fixedColumnOrder!3,!needsDividers!,!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard,!icon/next_key|!code/key_action_next"
private const val POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS = "!fixedColumnOrder!3,!needsDividers!,!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji"
private const val POPUP_EYS_NAVIGATE_EMOJI = "!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji"
private const val POPUP_EYS_NAVIGATE_EMOJI_NEXT = "!fixedColumnOrder!3,!needsDividers!,!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji,!icon/next_key|!code/key_action_next"
private const val POPUP_EYS_NAVIGATE_EMOJI_PREVIOUS_NEXT = "!fixedColumnOrder!4,!needsDividers!,!icon/previous_key|!code/key_action_previous,!icon/clipboard_action_key|!code/key_clipboard,!icon/emoji_action_key|!code/key_emoji,!icon/next_key|!code/key_action_next"
}
// make it non-nullable for simplicity, and to reflect current implementations
@ -145,7 +289,7 @@ sealed interface KeyData : AbstractKeyData {
require(groupId <= GROUP_ENTER) { "only groups up to GROUP_ENTER are supported" }
require(label.isNotEmpty() || type == KeyType.PLACEHOLDER || code != KeyCode.UNSPECIFIED) { "non-placeholder key has no code and no label" }
require(width >= 0f || width == -1f) { "illegal width $width" }
val newLabel = label.convertFlorisLabel()
val newLabel = label.convertFlorisLabel().resolveStringLabel(params)
val newCode = code.checkAndConvertCode()
val newLabelFlags = if (labelFlags == 0 && params.mId.isNumberLayout) {
if (type == KeyType.NUMERIC) {
@ -224,7 +368,7 @@ sealed interface KeyData : AbstractKeyData {
)
} else {
Key.KeyParams(
newLabel.rtlLabel(params), // todo (when supported): convert special labels to keySpec
newLabel.rtlLabel(params),
params,
newWidth,
newLabelFlags,
@ -251,7 +395,7 @@ sealed interface KeyData : AbstractKeyData {
KeyLabel.SYMBOL_ALPHA, KeyLabel.SYMBOL, KeyLabel.ALPHA, KeyLabel.COMMA, KeyLabel.PERIOD, KeyLabel.DELETE,
KeyLabel.EMOJI, KeyLabel.COM, KeyLabel.LANGUAGE_SWITCH, KeyLabel.NUMPAD -> return Key.BACKGROUND_TYPE_FUNCTIONAL
KeyLabel.SPACE, KeyLabel.ZWNJ -> return Key.BACKGROUND_TYPE_SPACEBAR
// KeyLabel.ACTION -> return Key.BACKGROUND_TYPE_ACTION
KeyLabel.ACTION -> return Key.BACKGROUND_TYPE_ACTION
KeyLabel.SHIFT -> return getShiftBackground(params)
}
if (type == KeyType.PLACEHOLDER) return Key.BACKGROUND_TYPE_EMPTY
@ -280,7 +424,7 @@ sealed interface KeyData : AbstractKeyData {
KeyLabel.COMMA -> params.mLocaleKeyboardInfos.labelComma
KeyLabel.PERIOD -> getPeriodLabel(params)
KeyLabel.SPACE -> getSpaceLabel(params)
// KeyLabel.ACTION -> "${getActionKeyLabel(params)}|${getActionKeyCode(params)}" would need context
KeyLabel.ACTION -> "${getActionKeyLabel(params)}|${getActionKeyCode(params)}"
KeyLabel.DELETE -> "!icon/delete_key|!code/key_delete"
KeyLabel.SHIFT -> "${getShiftLabel(params)}|!code/key_shift"
KeyLabel.EMOJI -> "!icon/emoji_normal_key|!code/key_emoji"
@ -308,16 +452,16 @@ sealed interface KeyData : AbstractKeyData {
}
}
// todo (later): add explanations / reasoning, often this is just taken from conversion from AOSP layouts
// todo (later): add explanations / reasoning, often this is just taken from conversion from OpenBoard / AOSP layouts
private fun getAdditionalLabelFlags(params: KeyboardParams): Int {
return when (label) {
KeyLabel.ALPHA, KeyLabel.SYMBOL_ALPHA, KeyLabel.SYMBOL -> Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR
KeyLabel.PERIOD, KeyLabel.COMMA -> Key.LABEL_FLAGS_HAS_POPUP_HINT // todo: period also has defaultLabelFlags -> when is this relevant?
// KeyLabel.ACTION -> {
// Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_AUTO_X_SCALE or
// Key.LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR or
// Key.LABEL_FLAGS_HAS_POPUP_HINT or KeyboardTheme.getThemeActionAndEmojiKeyLabelFlags(params.mThemeId)
// }
KeyLabel.ACTION -> {
Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_AUTO_X_SCALE or
Key.LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR or
Key.LABEL_FLAGS_HAS_POPUP_HINT or KeyboardTheme.getThemeActionAndEmojiKeyLabelFlags(params.mThemeId)
}
KeyLabel.SPACE -> if (params.mId.isNumberLayout) Key.LABEL_FLAGS_ALIGN_ICON_TO_BOTTOM else 0
KeyLabel.SHIFT -> Key.LABEL_FLAGS_PRESERVE_CASE or if (!params.mId.isAlphabetKeyboard) Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR else 0
KeyLabel.EMOJI -> KeyboardTheme.getThemeActionAndEmojiKeyLabelFlags(params.mThemeId)
@ -331,11 +475,11 @@ sealed interface KeyData : AbstractKeyData {
private fun getAdditionalPopupKeys(params: KeyboardParams): PopupSet<AbstractKeyData>? {
if (groupId == GROUP_COMMA) return SimplePopups(getCommaPopupKeys(params))
if (groupId == GROUP_PERIOD) return SimplePopups(getPunctuationPopupKeys(params))
// if (groupId == GROUP_ENTER) return getActionKeyPopupKeys(params)?.let { SimplePopups(it) }
if (groupId == GROUP_ENTER) return getActionKeyPopupKeys(params)
return when (label) {
KeyLabel.COMMA -> SimplePopups(getCommaPopupKeys(params))
KeyLabel.PERIOD -> SimplePopups(getPunctuationPopupKeys(params))
// KeyLabel.ACTION -> getActionKeyPopupKeys(params)?.let { SimplePopups(it) }
KeyLabel.ACTION -> getActionKeyPopupKeys(params)
KeyLabel.SHIFT -> {
if (params.mId.isAlphabetKeyboard) SimplePopups(
listOf(

View file

@ -23,6 +23,7 @@ import android.view.Gravity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import androidx.preference.PreferenceManager;
@ -692,4 +693,12 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public boolean isTablet() {
return mContext.getResources().getInteger(R.integer.config_screen_metrics) >= 3;
}
public int getStringResIdByName(final String name) {
return mContext.getResources().getIdentifier(name, "string", mContext.getPackageName());
}
public String getInLocale(@StringRes final int resId, final Locale locale) {
return RunInLocaleKt.runInLocale(mContext, locale, (ctx) -> ctx.getString(resId));
}
}