mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-06-10 16:39:35 +00:00
move that special handling for emoji and language switch keys into layouts
for that, a new keyboard_state_selector is added this allows modifying functional key layouts without having to manually adjust those keys
This commit is contained in:
parent
17f30ad6d6
commit
c064ba199c
6 changed files with 61 additions and 22 deletions
|
@ -84,6 +84,7 @@ Features that may go unnoticed, and further potentially useful information
|
||||||
* Select text and press shift to switch between uppercase, lowercase and capitalize words
|
* Select text and press shift to switch between uppercase, lowercase and capitalize words
|
||||||
* You can add dictionaries by opening the file
|
* You can add dictionaries by opening the file
|
||||||
* This only works with _content-uris_ and not with _file-uris_, meaning that it may not work with some file explorers.
|
* This only works with _content-uris_ and not with _file-uris_, meaning that it may not work with some file explorers.
|
||||||
|
* Not really a feature, but you can restart the keyboard by going to the settings and swiping it away from recents
|
||||||
* _Debug mode / debug APK_
|
* _Debug mode / debug APK_
|
||||||
* Long-press a suggestion in the suggestion strip twice to show the source dictionary.
|
* Long-press a suggestion in the suggestion strip twice to show the source dictionary.
|
||||||
* When using debug APK, you can find _Debug Settings_ within the _Advanced Preferences_, though the usefulness is limited except for dumping dictionaries into the log.
|
* When using debug APK, you can find _Debug Settings_ within the _Advanced Preferences_, though the usefulness is limited except for dumping dictionaries into the log.
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
"email": { "label": "@", "groupId": 1, "type": "function" },
|
"email": { "label": "@", "groupId": 1, "type": "function" },
|
||||||
"uri": { "label": "/", "groupId": 1, "type": "function" }
|
"uri": { "label": "/", "groupId": 1, "type": "function" }
|
||||||
},
|
},
|
||||||
{ "label": "language_switch" },
|
{ "$": "keyboard_state_selector", "languageKeyEnabled": { "$": "keyboard_state_selector", "alphabet": { "label": "language_switch" }}},
|
||||||
{ "label": "emoji" },
|
{ "$": "keyboard_state_selector", "emojiKeyEnabled": { "$": "keyboard_state_selector", "alphabet": { "label": "emoji" }}},
|
||||||
{ "label": "numpad" },
|
{ "$": "keyboard_state_selector", "symbols": { "label": "numpad" }},
|
||||||
{ "label": "space" },
|
{ "label": "space" },
|
||||||
{ "label": "period", "labelFlags": 1073741824 },
|
{ "label": "period", "labelFlags": 1073741824 },
|
||||||
{ "label": "action", "width": 0.15 }
|
{ "label": "action", "width": 0.15 }
|
||||||
|
|
|
@ -198,16 +198,7 @@ class KeyboardParser(private val params: KeyboardParams, private val context: Co
|
||||||
val functionalKeysBottom = allFunctionalKeys.lastOrNull() ?: return
|
val functionalKeysBottom = allFunctionalKeys.lastOrNull() ?: return
|
||||||
if (!params.mId.isAlphaOrSymbolKeyboard || functionalKeysBottom.isEmpty() || functionalKeysBottom.any { it.isKeyPlaceholder() })
|
if (!params.mId.isAlphaOrSymbolKeyboard || functionalKeysBottom.isEmpty() || functionalKeysBottom.any { it.isKeyPlaceholder() })
|
||||||
return
|
return
|
||||||
if (!Settings.getInstance().current.mHasCustomFunctionalLayout) {
|
// replace comma / period if 2 keys in normal bottom row
|
||||||
// remove keys that should only exist on specific layouts or depend on setting (emoji, numpad, language switch)
|
|
||||||
if (!Settings.getInstance().current.mShowsEmojiKey || !params.mId.isAlphabetKeyboard)
|
|
||||||
functionalKeysBottom.removeFirst { it.label == toolbarKeyStrings[ToolbarKey.EMOJI] }
|
|
||||||
if (!Settings.getInstance().current.isLanguageSwitchKeyEnabled || !params.mId.isAlphabetKeyboard)
|
|
||||||
functionalKeysBottom.removeFirst { it.label == KeyLabel.LANGUAGE_SWITCH }
|
|
||||||
if (params.mId.mElementId != KeyboardId.ELEMENT_SYMBOLS)
|
|
||||||
functionalKeysBottom.removeFirst { it.label == KeyLabel.NUMPAD }
|
|
||||||
}
|
|
||||||
// replace comma / period if 2 keys in normal bottom row
|
|
||||||
if (baseKeys.last().size == 2) {
|
if (baseKeys.last().size == 2) {
|
||||||
functionalKeysBottom.replaceFirst(
|
functionalKeysBottom.replaceFirst(
|
||||||
{ it.label == KeyLabel.COMMA || it.groupId == KeyData.GROUP_COMMA},
|
{ it.label == KeyLabel.COMMA || it.groupId == KeyData.GROUP_COMMA},
|
||||||
|
|
|
@ -11,6 +11,7 @@ import helium314.keyboard.keyboard.internal.keyboard_parser.floris.CaseSelector
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.CharWidthSelector
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.CharWidthSelector
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KanaSelector
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KanaSelector
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyData
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyData
|
||||||
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyboardStateSelector
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.LayoutDirectionSelector
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.LayoutDirectionSelector
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.MultiTextKeyData
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.MultiTextKeyData
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.ShiftStateSelector
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.ShiftStateSelector
|
||||||
|
@ -171,6 +172,7 @@ object RawKeyboardParser {
|
||||||
subclass(CaseSelector::class, CaseSelector.serializer())
|
subclass(CaseSelector::class, CaseSelector.serializer())
|
||||||
subclass(ShiftStateSelector::class, ShiftStateSelector.serializer())
|
subclass(ShiftStateSelector::class, ShiftStateSelector.serializer())
|
||||||
subclass(VariationSelector::class, VariationSelector.serializer())
|
subclass(VariationSelector::class, VariationSelector.serializer())
|
||||||
|
subclass(KeyboardStateSelector::class, KeyboardStateSelector.serializer())
|
||||||
subclass(LayoutDirectionSelector::class, LayoutDirectionSelector.serializer())
|
subclass(LayoutDirectionSelector::class, LayoutDirectionSelector.serializer())
|
||||||
subclass(CharWidthSelector::class, CharWidthSelector.serializer())
|
subclass(CharWidthSelector::class, CharWidthSelector.serializer())
|
||||||
subclass(KanaSelector::class, KanaSelector.serializer())
|
subclass(KanaSelector::class, KanaSelector.serializer())
|
||||||
|
|
|
@ -9,7 +9,6 @@ import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import helium314.keyboard.keyboard.KeyboardId
|
import helium314.keyboard.keyboard.KeyboardId
|
||||||
import helium314.keyboard.keyboard.internal.KeyboardParams
|
import helium314.keyboard.keyboard.internal.KeyboardParams
|
||||||
import helium314.keyboard.latin.common.StringUtils
|
|
||||||
|
|
||||||
// taken from FlorisBoard, small modifications
|
// taken from FlorisBoard, small modifications
|
||||||
// popup not nullable (maybe change back, but currently that's necessary for number keys)
|
// popup not nullable (maybe change back, but currently that's necessary for number keys)
|
||||||
|
@ -131,9 +130,7 @@ class ShiftStateSelector(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to select an [AbstractKeyData] based on the current variation. Note that this type of selector only really
|
* Allows to select an [AbstractKeyData] based on the current variation. The JSON class identifier for this selector is `variation_selector`.
|
||||||
* makes sense in a text context, though technically speaking it can be used anywhere, so this implementation allows
|
|
||||||
* for any [AbstractKeyData] to be used here. The JSON class identifier for this selector is `variation_selector`.
|
|
||||||
*
|
*
|
||||||
* Example usage in a layout JSON file:
|
* Example usage in a layout JSON file:
|
||||||
* ```
|
* ```
|
||||||
|
@ -155,6 +152,12 @@ class ShiftStateSelector(
|
||||||
* [default] will be used instead.
|
* [default] will be used instead.
|
||||||
* @property password The key data to use if [KeyboardId.passwordInput] return true. If this value is
|
* @property password The key data to use if [KeyboardId.passwordInput] return true. If this value is
|
||||||
* null, [default] will be used instead.
|
* null, [default] will be used instead.
|
||||||
|
* @property date The key data to use if [KeyboardId.MODE_DATE] is active. If this value is null,
|
||||||
|
* null, [default] will be used instead.
|
||||||
|
* @property time The key data to use if [KeyboardId.MODE_TIME] is active. If this value is null,
|
||||||
|
* null, [default] will be used instead.
|
||||||
|
* @property datetime The key data to use if [KeyboardId.MODE_DATETIME] is active. If this value is null,
|
||||||
|
* null, [default] will be used instead.
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("variation_selector")
|
@SerialName("variation_selector")
|
||||||
|
@ -170,16 +173,13 @@ data class VariationSelector(
|
||||||
) : AbstractKeyData {
|
) : AbstractKeyData {
|
||||||
override fun compute(params: KeyboardParams): KeyData? {
|
override fun compute(params: KeyboardParams): KeyData? {
|
||||||
return when {
|
return when {
|
||||||
// todo: what is normal and all?
|
|
||||||
// KeyVariation.ALL -> default
|
|
||||||
// KeyVariation.NORMAL -> normal ?: default
|
|
||||||
params.mId.passwordInput() -> password ?: default
|
params.mId.passwordInput() -> password ?: default
|
||||||
params.mId.mMode == KeyboardId.MODE_EMAIL -> email ?: default
|
params.mId.mMode == KeyboardId.MODE_EMAIL -> email ?: default
|
||||||
params.mId.mMode == KeyboardId.MODE_URL -> uri ?: default
|
params.mId.mMode == KeyboardId.MODE_URL -> uri ?: default
|
||||||
params.mId.mMode == KeyboardId.MODE_DATE -> date ?: default
|
params.mId.mMode == KeyboardId.MODE_DATE -> date ?: default
|
||||||
params.mId.mMode == KeyboardId.MODE_TIME -> time ?: default
|
params.mId.mMode == KeyboardId.MODE_TIME -> time ?: default
|
||||||
params.mId.mMode == KeyboardId.MODE_DATETIME -> datetime ?: default
|
params.mId.mMode == KeyboardId.MODE_DATETIME -> datetime ?: default
|
||||||
else -> default
|
else -> normal ?: default
|
||||||
}?.compute(params)
|
}?.compute(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +188,49 @@ data class VariationSelector(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to select an [AbstractKeyData] based on states saved in [KeyboardId].
|
||||||
|
* The JSON class identifier for this selector is `keyboard_state_selector`.
|
||||||
|
* Note that the conditions are checked in order as given below, and the first non-null AbstractKeyData is selected.
|
||||||
|
*
|
||||||
|
* @property emojiKeyEnabled The key data to use if [KeyboardId.mEmojiKeyEnabled] is true.
|
||||||
|
* @property languageKeyEnabled The key data to use if [KeyboardId.mLanguageSwitchKeyEnabled] is true.
|
||||||
|
* @property symbols The key data to use if [KeyboardId.mElementId] is [KeyboardId.ELEMENT_SYMBOLS].
|
||||||
|
* @property moreSymbols The key data to use if [KeyboardId.mElementId] is [KeyboardId.ELEMENT_SYMBOLS_SHIFTED].
|
||||||
|
* @property alphabet The key data to use if [KeyboardId.isAlphabetKeyboard] is true.
|
||||||
|
* @property default The default key data which should be used in case none of the other conditions have a matching non-null
|
||||||
|
* AbstractKeyData. Can be null, in this case no key is displayed.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
@SerialName("keyboard_state_selector")
|
||||||
|
class KeyboardStateSelector(
|
||||||
|
val emojiKeyEnabled: AbstractKeyData? = null,
|
||||||
|
val languageKeyEnabled: AbstractKeyData? = null,
|
||||||
|
val symbols: AbstractKeyData? = null,
|
||||||
|
val moreSymbols: AbstractKeyData? = null,
|
||||||
|
val alphabet: AbstractKeyData? = null,
|
||||||
|
val default: AbstractKeyData? = null,
|
||||||
|
) : AbstractKeyData {
|
||||||
|
override fun compute(params: KeyboardParams): KeyData? {
|
||||||
|
if (params.mId.mEmojiKeyEnabled)
|
||||||
|
emojiKeyEnabled?.compute(params)?.let { return it }
|
||||||
|
if (params.mId.mLanguageSwitchKeyEnabled)
|
||||||
|
languageKeyEnabled?.compute(params)?.let { return it }
|
||||||
|
if (params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS)
|
||||||
|
symbols?.compute(params)?.let { return it }
|
||||||
|
if (params.mId.mElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED)
|
||||||
|
moreSymbols?.compute(params)?.let { return it }
|
||||||
|
if (params.mId.isAlphabetKeyboard)
|
||||||
|
alphabet?.compute(params)?.let { return it }
|
||||||
|
|
||||||
|
return default?.compute(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun asString(isForDisplay: Boolean): String {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to select an [AbstractKeyData] based on the current layout direction. Note that this type of selector only
|
* Allows to select an [AbstractKeyData] based on the current layout direction. Note that this type of selector only
|
||||||
* really makes sense in a text context, though technically speaking it can be used anywhere, so this implementation
|
* really makes sense in a text context, though technically speaking it can be used anywhere, so this implementation
|
||||||
|
|
|
@ -33,7 +33,9 @@ If the layout has exactly 2 keys in the bottom row, these keys will replace comm
|
||||||
* there are also selector classes, which allow to change keys conditionally, see the [dvorak layout](https://github.com/Helium314/HeliBoard/blob/main/app/src/main/assets/layouts/dvorak.json) for an example:
|
* there are also selector classes, which allow to change keys conditionally, see the [dvorak layout](https://github.com/Helium314/HeliBoard/blob/main/app/src/main/assets/layouts/dvorak.json) for an example:
|
||||||
* `case_selector`: keys for `lower` and `upper` (both mandatory), similar to `shift_state_selector`
|
* `case_selector`: keys for `lower` and `upper` (both mandatory), similar to `shift_state_selector`
|
||||||
* `shift_state_selector`: keys for `unshifted`, `shifted`, `shiftedManual`, `shiftedAutomatic`, `capsLock`, `manualOrLocked`, `default` (all optional)
|
* `shift_state_selector`: keys for `unshifted`, `shifted`, `shiftedManual`, `shiftedAutomatic`, `capsLock`, `manualOrLocked`, `default` (all optional)
|
||||||
* `variation_selector`: keys for `datetime`, `time`, `date`, `password`, `normal`, `uri`, `email`, `default` (all optional)
|
* `variation_selector`: keys for input types `datetime`, `time`, `date`, `password`, `normal`, `uri`, `email`, `default` (all optional)
|
||||||
|
* `keyboard_state_selector`: keys for `emojiKeyEnabled`, `languageKeyEnabled`, `symbols`, `moreSymbols`, `alphabet`, `default` (all optional)
|
||||||
|
* the `keyEnabled` keys will be used if the corresponding setting is enabled, `symbols`, `moreSymbols`, `alphabet` will be used when the said keyboard view is active
|
||||||
* `layout_direction_selector`: keys for `ltr` and `rtl` (both mandatory)
|
* `layout_direction_selector`: keys for `ltr` and `rtl` (both mandatory)
|
||||||
### Properties
|
### Properties
|
||||||
* A (non-selector) key can have the following properties:
|
* A (non-selector) key can have the following properties:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue