mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-16 15:02:48 +00:00
add new parser for emoji arrays
This commit is contained in:
parent
4406f1b224
commit
615fde1a7b
4 changed files with 168 additions and 17 deletions
|
@ -1326,6 +1326,47 @@ public class Key implements Comparable<Key> {
|
|||
mEnabled = true;
|
||||
}
|
||||
|
||||
/** constructor for emoji parser */ // essentially the same as the GridRows constructor, but without coordinates and outputText
|
||||
public KeyParams(@Nullable final String label, final int code, @Nullable final String hintLabel,
|
||||
@Nullable final String moreKeySpecs, final int labelFlags, final KeyboardParams params) {
|
||||
mKeyboardParams = params;
|
||||
mHintLabel = hintLabel;
|
||||
mLabelFlags = labelFlags;
|
||||
mBackgroundType = BACKGROUND_TYPE_EMPTY;
|
||||
|
||||
if (moreKeySpecs != null) {
|
||||
String[] moreKeys = MoreKeySpec.splitKeySpecs(moreKeySpecs);
|
||||
mMoreKeysColumnAndFlags = getMoreKeysColumnAndFlagsAndSetNullInArray(params, moreKeys);
|
||||
|
||||
moreKeys = MoreKeySpec.insertAdditionalMoreKeys(moreKeys, null);
|
||||
int actionFlags = 0;
|
||||
if (moreKeys != null) {
|
||||
actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS;
|
||||
mMoreKeys = new MoreKeySpec[moreKeys.length];
|
||||
for (int i = 0; i < moreKeys.length; i++) {
|
||||
mMoreKeys[i] = new MoreKeySpec(moreKeys[i], false, Locale.getDefault());
|
||||
}
|
||||
} else {
|
||||
mMoreKeys = null;
|
||||
}
|
||||
mActionFlags = actionFlags;
|
||||
} else {
|
||||
// TODO: Pass keyActionFlags as an argument.
|
||||
mActionFlags = ACTION_FLAGS_NO_KEY_PREVIEW;
|
||||
mMoreKeys = null;
|
||||
mMoreKeysColumnAndFlags = 0;
|
||||
}
|
||||
|
||||
mLabel = label;
|
||||
mOptionalAttributes = code == Constants.CODE_OUTPUT_TEXT
|
||||
? OptionalAttributes.newInstance(label, CODE_UNSPECIFIED, ICON_UNDEFINED, 0, 0)
|
||||
: null;
|
||||
mCode = code;
|
||||
mEnabled = (code != CODE_UNSPECIFIED);
|
||||
mIconId = KeyboardIconsSet.ICON_UNDEFINED;
|
||||
mKeyVisualAttributes = null;
|
||||
}
|
||||
|
||||
/** constructor for <GridRows/> */
|
||||
public KeyParams(@Nullable final String label, final int code, @Nullable final String outputText,
|
||||
@Nullable final String hintLabel, @Nullable final String moreKeySpecs,
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.keyboard.emoji;
|
||||
|
||||
import static org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.EmojiParserKt.EMOJI_HINT_LABEL;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
@ -115,7 +117,7 @@ final class DynamicGridKeyboard extends Keyboard {
|
|||
// if key comes from another keyboard (ie. a {@link MoreKeysKeyboard}).
|
||||
final boolean dropMoreKeys = mIsRecents;
|
||||
// Check if hint was a more emoji indicator and prevent its copy if more keys aren't copied
|
||||
final boolean dropHintLabel = dropMoreKeys && "\u25E5".equals(usedKey.getHintLabel());
|
||||
final boolean dropHintLabel = dropMoreKeys && EMOJI_HINT_LABEL.equals(usedKey.getHintLabel());
|
||||
final GridKey key = new GridKey(usedKey,
|
||||
dropMoreKeys ? null : usedKey.getMoreKeys(),
|
||||
dropHintLabel ? null : usedKey.getHintLabel(),
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.dslul.openboard.inputmethod.keyboard.Key
|
|||
import org.dslul.openboard.inputmethod.keyboard.Key.KeyParams
|
||||
import org.dslul.openboard.inputmethod.keyboard.Keyboard
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardId
|
||||
import org.dslul.openboard.inputmethod.keyboard.MoreKeysKeyboard
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.EmojiParser
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.KeyboardParser
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.XmlKeyboardParser
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.addLocaleKeyTextsToParams
|
||||
|
@ -25,7 +25,6 @@ import org.dslul.openboard.inputmethod.latin.R
|
|||
import org.dslul.openboard.inputmethod.latin.common.Constants
|
||||
import org.dslul.openboard.inputmethod.latin.define.DebugFlags
|
||||
import org.dslul.openboard.inputmethod.latin.settings.Settings
|
||||
import org.dslul.openboard.inputmethod.latin.suggestions.MoreSuggestions
|
||||
import org.dslul.openboard.inputmethod.latin.utils.sumOf
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import org.xmlpull.v1.XmlPullParserException
|
||||
|
@ -68,18 +67,6 @@ open class KeyboardBuilder<KP : KeyboardParams>(protected val mContext: Context,
|
|||
return this
|
||||
|
||||
// todo: further plan
|
||||
// make the remove duplicate moreKey thing an option?
|
||||
// why is it on for serbian (latin), but not for german (german)?
|
||||
// only nordic and serbian_qwertz layouts have it disabled, default is enabled
|
||||
// -> add the option, but disable it by default for all layouts
|
||||
// migrate emoji layouts to this style
|
||||
// emojis are defined in that string array, should be simple to handle
|
||||
// parsing could be done into a single row, which is then split as needed
|
||||
// this might help with split layout (no change in key size, but in number of rows)
|
||||
// write another parser, it should already consider split
|
||||
// add a setting to display all emojis (and use emojiv2 or emojicompat or whatever is necessary)
|
||||
// mention in subtitle that they may not be displayed properly, depending on the app you're writing in
|
||||
// uncomment the toast below
|
||||
// number layouts missing details
|
||||
// landscape: numpad layout has some extra keys
|
||||
// tablet: number and phone layout have some extra keys (unify with numpad, so that extra keys show both in land and sw600? or only land?)
|
||||
|
@ -165,6 +152,12 @@ open class KeyboardBuilder<KP : KeyboardParams>(protected val mContext: Context,
|
|||
readAttributes(xmlId)
|
||||
return this
|
||||
}
|
||||
if (id.mElementId >= KeyboardId.ELEMENT_EMOJI_RECENTS && id.mElementId <= KeyboardId.ELEMENT_EMOJI_CATEGORY16) {
|
||||
mParams.mId = id
|
||||
readAttributes(R.xml.kbd_emoji_category1) // all the same anyway, gridRows are ignored
|
||||
keysInRows = EmojiParser(mParams, mContext).parse(Settings.getInstance().current.mIsSplitKeyboardEnabled)
|
||||
return this
|
||||
}
|
||||
if (loadFromAssets(id) != null) {
|
||||
if (!DebugFlags.DEBUG_ENABLED)
|
||||
return this
|
||||
|
@ -242,8 +235,7 @@ open class KeyboardBuilder<KP : KeyboardParams>(protected val mContext: Context,
|
|||
if (DebugFlags.DEBUG_ENABLED) {
|
||||
// looks like only emoji keyboards are still using the old parser, which is expected
|
||||
Log.w(TAG, "falling back to old parser for $id")
|
||||
if (mParams.mId.mElementId < KeyboardId.ELEMENT_EMOJI_RECENTS || mParams.mId.mElementId > KeyboardId.ELEMENT_EMOJI_CATEGORY16)
|
||||
Toast.makeText(mContext, "using old parser for $id", Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(mContext, "using old parser for $id", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
mParams.mId = id
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
package org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import org.dslul.openboard.inputmethod.keyboard.Key
|
||||
import org.dslul.openboard.inputmethod.keyboard.Key.KeyParams
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardId
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardParams
|
||||
import org.dslul.openboard.inputmethod.latin.R
|
||||
import org.dslul.openboard.inputmethod.latin.common.Constants
|
||||
import org.dslul.openboard.inputmethod.latin.common.StringUtils
|
||||
|
||||
class EmojiParser(private val params: KeyboardParams, private val context: Context) {
|
||||
|
||||
fun parse(splitKeyboard: Boolean): ArrayList<ArrayList<KeyParams>> { // todo: split should be read from params, but currently this is disabled, right?
|
||||
val emojiArrayId = when (params.mId.mElementId) {
|
||||
KeyboardId.ELEMENT_EMOJI_RECENTS -> R.array.emoji_recents
|
||||
KeyboardId.ELEMENT_EMOJI_CATEGORY1 -> R.array.emoji_smileys_emotion
|
||||
KeyboardId.ELEMENT_EMOJI_CATEGORY2 -> R.array.emoji_people_body
|
||||
KeyboardId.ELEMENT_EMOJI_CATEGORY3 -> R.array.emoji_animals_nature
|
||||
KeyboardId.ELEMENT_EMOJI_CATEGORY4 -> R.array.emoji_food_drink
|
||||
KeyboardId.ELEMENT_EMOJI_CATEGORY5 -> R.array.emoji_travel_places
|
||||
KeyboardId.ELEMENT_EMOJI_CATEGORY6 -> R.array.emoji_activities
|
||||
KeyboardId.ELEMENT_EMOJI_CATEGORY7 -> R.array.emoji_objects
|
||||
KeyboardId.ELEMENT_EMOJI_CATEGORY8 -> R.array.emoji_symbols
|
||||
KeyboardId.ELEMENT_EMOJI_CATEGORY9 -> R.array.emoji_flags
|
||||
KeyboardId.ELEMENT_EMOJI_CATEGORY10 -> R.array.emoji_emoticons
|
||||
else -> throw(IllegalStateException("can only parse emoji categories where an array exists"))
|
||||
}
|
||||
val emojiArray = context.resources.getStringArray(emojiArrayId)
|
||||
val moreEmojisArray = if (params.mId.mElementId == KeyboardId.ELEMENT_EMOJI_CATEGORY2)
|
||||
context.resources.getStringArray(R.array.emoji_people_body_more)
|
||||
else null
|
||||
if (moreEmojisArray != null && emojiArray.size != moreEmojisArray.size)
|
||||
throw(IllegalStateException("Inconsistent array size between codesArray and moreKeysArray"))
|
||||
|
||||
// now we have the params in one long list -> split into lines and maybe add spacer
|
||||
// todo: disabled, because it doesn't work properly... spacer keys get added to the end every 3 rows
|
||||
// the sorting and sizing seems to be done in DynamicGridKeyboard
|
||||
// only the template keys there are relevant for dimensions, resizing keys here doesn't have any effect
|
||||
// -> this is really weird and unexpected, and should be changed (might also help with the text emojis...)
|
||||
/* val numColumns = (1 / params.mDefaultRelativeKeyWidth).toInt()
|
||||
val spacerNumKeys: Int
|
||||
val spacerWidth: Float
|
||||
if (splitKeyboard) {
|
||||
val spacerRelativeWidth = Settings.getInstance().current.mSpacerRelativeWidth
|
||||
// adjust gaps for the whole keyboard, so it's the same for all rows
|
||||
params.mRelativeHorizontalGap *= 1f / (1f + spacerRelativeWidth)
|
||||
params.mHorizontalGap = (params.mRelativeHorizontalGap * params.mId.mWidth).toInt()
|
||||
// round the spacer width, so it's a number of keys, and number should be even if emoji count is even, odd otherwise
|
||||
spacerNumKeys = (spacerRelativeWidth / params.mDefaultRelativeKeyWidth).roundTo(numColumns % 2 == 0)
|
||||
spacerWidth = spacerNumKeys * params.mDefaultRelativeKeyWidth
|
||||
} else {
|
||||
spacerNumKeys = 0
|
||||
spacerWidth = 0f
|
||||
}
|
||||
val spacerIndex = if (spacerNumKeys > 0) (numColumns - spacerNumKeys) / 2 else -1
|
||||
*/
|
||||
val row = ArrayList<KeyParams>(emojiArray.size)
|
||||
var currentX = params.mLeftPadding.toFloat()
|
||||
val currentY = params.mTopPadding.toFloat()
|
||||
emojiArray.forEachIndexed { i, codeArraySpec ->
|
||||
val keyParams = parseEmojiKey(codeArraySpec, moreEmojisArray?.get(i)?.takeIf { it.isNotEmpty() }) ?: return@forEachIndexed
|
||||
keyParams.setDimensionsFromRelativeSize(currentX, currentY)
|
||||
currentX += keyParams.mFullWidth // exact value seems to be not really relevant, but keeping 0 doesn't work
|
||||
row.add(keyParams)
|
||||
// if (row.size % numColumns == spacerIndex) { // also removed for now (would be missing setting the size and updating x
|
||||
// repeat(spacerNumKeys) { row.add(KeyParams.newSpacer(params, params.mDefaultRelativeKeyWidth)) }
|
||||
// }
|
||||
}
|
||||
return arrayListOf(row)
|
||||
}
|
||||
|
||||
// private fun Float.roundTo(even: Boolean) = if (toInt() % 2 == if (even) 0 else 1) toInt() else toInt() + 1
|
||||
|
||||
private fun getLabelAndCode(spec: String): Pair<String, Int>? {
|
||||
val specAndSdk = spec.split("||")
|
||||
if (specAndSdk.getOrNull(1)?.toIntOrNull()?.let { it > Build.VERSION.SDK_INT } == true) return null
|
||||
if ("," !in specAndSdk.first()) {
|
||||
val code = specAndSdk.first().toIntOrNull(16) ?: return specAndSdk.first() to Constants.CODE_OUTPUT_TEXT // text emojis
|
||||
val label = StringUtils.newSingleCodePointString(code)
|
||||
return label to code
|
||||
}
|
||||
val labelBuilder = StringBuilder()
|
||||
for (codePointString in specAndSdk.first().split(",")) {
|
||||
val cp = codePointString.toInt(16)
|
||||
labelBuilder.appendCodePoint(cp)
|
||||
}
|
||||
return labelBuilder.toString() to Constants.CODE_OUTPUT_TEXT
|
||||
}
|
||||
|
||||
private fun parseEmojiKey(spec: String, moreKeysString: String? = null): Key.KeyParams? {
|
||||
val (label, code) = getLabelAndCode(spec) ?: return null
|
||||
val sb = StringBuilder()
|
||||
moreKeysString?.split(";")?.let { moreKeys ->
|
||||
moreKeys.forEach {
|
||||
val (mkLabel, _) = getLabelAndCode(it) ?: return@forEach
|
||||
sb.append(mkLabel).append(",")
|
||||
}
|
||||
}
|
||||
val moreKeysSpec = if (sb.isNotEmpty()) {
|
||||
sb.deleteCharAt(sb.length - 1)
|
||||
sb.toString()
|
||||
} else null
|
||||
return KeyParams(
|
||||
label,
|
||||
code,
|
||||
if (moreKeysSpec != null) EMOJI_HINT_LABEL else null,
|
||||
moreKeysSpec,
|
||||
Key.LABEL_FLAGS_FONT_NORMAL,
|
||||
params
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const val EMOJI_HINT_LABEL = "◥"
|
Loading…
Add table
Add a link
Reference in a new issue