mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Update input logic to better handle combined emoji
This commit is contained in:
parent
9410e5a825
commit
536460cfd4
@ -23474,5 +23474,27 @@
|
||||
]
|
||||
, "unicode_version": "11.0"
|
||||
, "ios_version": "12.1"
|
||||
},
|
||||
{
|
||||
"emoji": ":)"
|
||||
, "description": "smiley"
|
||||
, "category": "ASCII"
|
||||
, "aliases": [
|
||||
]
|
||||
, "tags": [
|
||||
]
|
||||
, "unicode_version": ""
|
||||
, "ios_version": ""
|
||||
}
|
||||
, {
|
||||
"emoji": ":3"
|
||||
, "description": "cat face"
|
||||
, "category": "ASCII"
|
||||
, "aliases": [
|
||||
]
|
||||
, "tags": [
|
||||
]
|
||||
, "unicode_version": ""
|
||||
, "ios_version": ""
|
||||
}
|
||||
]
|
||||
|
@ -37,14 +37,17 @@ import androidx.savedstate.SavedStateRegistryController
|
||||
import androidx.savedstate.SavedStateRegistryOwner
|
||||
import androidx.savedstate.findViewTreeSavedStateRegistryOwner
|
||||
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.futo.inputmethod.latin.SuggestedWords.SuggestedWordInfo
|
||||
import org.futo.inputmethod.latin.common.Constants
|
||||
import org.futo.inputmethod.latin.uix.BasicThemeProvider
|
||||
import org.futo.inputmethod.latin.uix.DynamicThemeProvider
|
||||
import org.futo.inputmethod.latin.uix.DynamicThemeProviderOwner
|
||||
import org.futo.inputmethod.latin.uix.EmojiTracker.unuseEmoji
|
||||
import org.futo.inputmethod.latin.uix.EmojiTracker.useEmoji
|
||||
import org.futo.inputmethod.latin.uix.SUGGESTION_BLACKLIST
|
||||
import org.futo.inputmethod.latin.uix.THEME_KEY
|
||||
@ -542,7 +545,17 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
fun rememberEmojiSuggestion(suggestion: SuggestedWordInfo) {
|
||||
if(suggestion.mKindAndFlags == SuggestedWordInfo.KIND_EMOJI_SUGGESTION) {
|
||||
lifecycleScope.launch {
|
||||
useEmoji(suggestion.mWord)
|
||||
withContext(Dispatchers.Default) {
|
||||
useEmoji(suggestion.mWord)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onEmojiDeleted(emoji: String) {
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.Default) {
|
||||
unuseEmoji(emoji)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2048,4 +2048,8 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
public LanguageModelFacilitator getLanguageModelFacilitator() {
|
||||
return ((LatinIME)(mInputMethodService)).getLanguageModelFacilitator();
|
||||
}
|
||||
|
||||
public void onCodePointDeleted(String textBeforeCursor) {
|
||||
((LatinIME)(mInputMethodService)).onEmojiDeleted(textBeforeCursor);
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ import org.futo.inputmethod.latin.utils.StatsUtils;
|
||||
import org.futo.inputmethod.latin.utils.TextRange;
|
||||
import org.futo.inputmethod.latin.xlm.LanguageModelFacilitator;
|
||||
|
||||
import java.text.BreakIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.TreeSet;
|
||||
@ -1072,6 +1073,7 @@ public final class InputLogic {
|
||||
// like the smiley key or the .com key.
|
||||
mConnection.deleteTextBeforeCursor(mEnteredText.length());
|
||||
StatsUtils.onDeleteMultiCharInput(mEnteredText.length());
|
||||
mLatinIMELegacy.onCodePointDeleted(mEnteredText);
|
||||
mEnteredText = null;
|
||||
// If we have mEnteredText, then we know that mHasUncommittedTypedChars == false.
|
||||
// In addition we know that spaceState is false, and that we should not be
|
||||
@ -1159,8 +1161,26 @@ public final class InputLogic {
|
||||
// TODO: Add a new StatsUtils method onBackspaceWhenNoText()
|
||||
return;
|
||||
}
|
||||
final int lengthToDelete =
|
||||
|
||||
String textDeleted = new String(Character.toChars(codePointBeforeCursor));
|
||||
int lengthToDelete =
|
||||
Character.isSupplementaryCodePoint(codePointBeforeCursor) ? 2 : 1;
|
||||
|
||||
// Handle emoji sequences (flags, etc)
|
||||
CharSequence textBeforeCursor = mConnection.getTextBeforeCursor(8, 0);
|
||||
if (textBeforeCursor != null && textBeforeCursor.length() > 0) {
|
||||
BreakIterator breakIterator = BreakIterator.getCharacterInstance();
|
||||
breakIterator.setText(textBeforeCursor.toString());
|
||||
int end = breakIterator.last();
|
||||
int start = breakIterator.previous();
|
||||
|
||||
if (start != BreakIterator.DONE) {
|
||||
lengthToDelete = end - start;
|
||||
textDeleted = textBeforeCursor.subSequence(start, end).toString();
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "lengthToDelete=" + lengthToDelete + ", textDeleted=" + textDeleted);
|
||||
mConnection.deleteTextBeforeCursor(lengthToDelete);
|
||||
int totalDeletedLength = lengthToDelete;
|
||||
if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) {
|
||||
@ -1179,6 +1199,9 @@ public final class InputLogic {
|
||||
}
|
||||
}
|
||||
StatsUtils.onBackspacePressed(totalDeletedLength);
|
||||
|
||||
if(codePointBeforeCursor >= 0x1F600)
|
||||
mLatinIMELegacy.onCodePointDeleted(textDeleted);
|
||||
}
|
||||
}
|
||||
if (!hasUnlearnedWordBeingDeleted) {
|
||||
|
@ -25,7 +25,7 @@ object EmojiTracker {
|
||||
suspend fun Context.unuseEmoji(emoji: String) {
|
||||
dataStore.edit {
|
||||
val split = (it[lastUsedEmoji] ?: "").split("<|>")
|
||||
val idxToRemove = split.indexOfFirst { v -> v == emoji }
|
||||
val idxToRemove = split.indexOfFirst { v -> v == emoji || v.trim() == emoji.trim() }
|
||||
it[lastUsedEmoji] = split.filterIndexed { i, _ -> i != idxToRemove}.joinToString("<|>")
|
||||
}
|
||||
}
|
||||
|
@ -113,8 +113,10 @@ class EmojiGridAdapter(
|
||||
fun bindEmoji(
|
||||
emoji: EmojiItem,
|
||||
onClick: (EmojiItem) -> Unit,
|
||||
onSelectSkinTone: (PopupInfo) -> Unit
|
||||
onSelectSkinTone: (PopupInfo) -> Unit,
|
||||
color: Int
|
||||
) {
|
||||
emojiView.setTextColor(color)
|
||||
emojiView.emoji = emoji
|
||||
emojiView.setOnClickListener {
|
||||
it.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT)
|
||||
@ -153,7 +155,7 @@ class EmojiGridAdapter(
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val item = data[position]
|
||||
if(item is EmojiItemItem && holder is EmojiViewHolder) {
|
||||
holder.bindEmoji(item.emoji, onClick, onSelectSkinTone)
|
||||
holder.bindEmoji(item.emoji, onClick, onSelectSkinTone, contentColor.toArgb())
|
||||
}else if(item is CategoryItem && holder is CategoryViewHolder) {
|
||||
holder.bind(item)
|
||||
}
|
||||
|
@ -67,6 +67,10 @@ class EmojiView @JvmOverloads constructor(
|
||||
)
|
||||
}
|
||||
|
||||
fun setTextColor(color: Int) {
|
||||
textPaint.color = color
|
||||
}
|
||||
|
||||
private val offscreenCanvasBitmap: Bitmap = with(textPaint.fontMetricsInt) {
|
||||
val size = bottom - top
|
||||
Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
|
||||
|
Loading…
Reference in New Issue
Block a user