mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-16 23:12:47 +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;
|
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/> */
|
/** constructor for <GridRows/> */
|
||||||
public KeyParams(@Nullable final String label, final int code, @Nullable final String outputText,
|
public KeyParams(@Nullable final String label, final int code, @Nullable final String outputText,
|
||||||
@Nullable final String hintLabel, @Nullable final String moreKeySpecs,
|
@Nullable final String hintLabel, @Nullable final String moreKeySpecs,
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
package org.dslul.openboard.inputmethod.keyboard.emoji;
|
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.content.SharedPreferences;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -115,7 +117,7 @@ final class DynamicGridKeyboard extends Keyboard {
|
||||||
// if key comes from another keyboard (ie. a {@link MoreKeysKeyboard}).
|
// if key comes from another keyboard (ie. a {@link MoreKeysKeyboard}).
|
||||||
final boolean dropMoreKeys = mIsRecents;
|
final boolean dropMoreKeys = mIsRecents;
|
||||||
// Check if hint was a more emoji indicator and prevent its copy if more keys aren't copied
|
// 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,
|
final GridKey key = new GridKey(usedKey,
|
||||||
dropMoreKeys ? null : usedKey.getMoreKeys(),
|
dropMoreKeys ? null : usedKey.getMoreKeys(),
|
||||||
dropHintLabel ? null : usedKey.getHintLabel(),
|
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.Key.KeyParams
|
||||||
import org.dslul.openboard.inputmethod.keyboard.Keyboard
|
import org.dslul.openboard.inputmethod.keyboard.Keyboard
|
||||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardId
|
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.KeyboardParser
|
||||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.XmlKeyboardParser
|
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.XmlKeyboardParser
|
||||||
import org.dslul.openboard.inputmethod.keyboard.internal.keyboard_parser.addLocaleKeyTextsToParams
|
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.common.Constants
|
||||||
import org.dslul.openboard.inputmethod.latin.define.DebugFlags
|
import org.dslul.openboard.inputmethod.latin.define.DebugFlags
|
||||||
import org.dslul.openboard.inputmethod.latin.settings.Settings
|
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.dslul.openboard.inputmethod.latin.utils.sumOf
|
||||||
import org.xmlpull.v1.XmlPullParser
|
import org.xmlpull.v1.XmlPullParser
|
||||||
import org.xmlpull.v1.XmlPullParserException
|
import org.xmlpull.v1.XmlPullParserException
|
||||||
|
@ -68,18 +67,6 @@ open class KeyboardBuilder<KP : KeyboardParams>(protected val mContext: Context,
|
||||||
return this
|
return this
|
||||||
|
|
||||||
// todo: further plan
|
// 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
|
// number layouts missing details
|
||||||
// landscape: numpad layout has some extra keys
|
// 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?)
|
// 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)
|
readAttributes(xmlId)
|
||||||
return this
|
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 (loadFromAssets(id) != null) {
|
||||||
if (!DebugFlags.DEBUG_ENABLED)
|
if (!DebugFlags.DEBUG_ENABLED)
|
||||||
return this
|
return this
|
||||||
|
@ -242,7 +235,6 @@ open class KeyboardBuilder<KP : KeyboardParams>(protected val mContext: Context,
|
||||||
if (DebugFlags.DEBUG_ENABLED) {
|
if (DebugFlags.DEBUG_ENABLED) {
|
||||||
// looks like only emoji keyboards are still using the old parser, which is expected
|
// looks like only emoji keyboards are still using the old parser, which is expected
|
||||||
Log.w(TAG, "falling back to old parser for $id")
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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