mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-14 14:02:44 +00:00
(partially) remove workaround for key params
This commit is contained in:
parent
5b4ba11fb7
commit
2466187eb3
4 changed files with 168 additions and 168 deletions
|
@ -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"
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue