Add EmojiAction

This commit is contained in:
Aleksandras Kostarevas 2023-11-28 19:23:51 +00:00
parent 4f15ff4a73
commit 88403fad79
11 changed files with 23820 additions and 72 deletions

View File

@ -165,6 +165,7 @@ dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.5.1'
def work_version = "2.8.1"
implementation "androidx.work:work-runtime-ktx:$work_version"

76
java/res/drawable/cpu.xml Normal file
View File

@ -0,0 +1,76 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M6,4L18,4A2,2 0,0 1,20 6L20,18A2,2 0,0 1,18 20L6,20A2,2 0,0 1,4 18L4,6A2,2 0,0 1,6 4z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M9,9h6v6h-6z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M9,1L9,4"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M15,1L15,4"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M9,20L9,23"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M15,20L15,23"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M20,9L23,9"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M20,14L23,14"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M1,9L4,9"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M1,14L4,14"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M8,14s1.5,2 4,2 4,-2 4,-2"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M9,9L9.01,9"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M15,9L15.01,9"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
</vector>

23479
java/res/raw/gemoji.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -573,4 +573,5 @@ Tip: You can download and remove dictionaries by going to &lt;b>Languages&#160;&
This resource is copied from packages/apps/Settings/res/values/strings.xml -->
<!-- This resource is corresponding to msgid="5433275485499039199" -->
<string name="user_dict_fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
<string name="title_emojis">Emojis</string>
</resources>

View File

@ -1,6 +1,5 @@
package org.futo.inputmethod.latin
import android.content.ComponentCallbacks2
import android.content.Context
import android.content.res.Configuration
import android.inputmethodservice.InputMethodService
@ -8,10 +7,8 @@ import android.os.Build
import android.os.Bundle
import android.view.KeyEvent
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.CompletionInfo
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InlineSuggestion
import android.view.inputmethod.InlineSuggestionsRequest
import android.view.inputmethod.InlineSuggestionsResponse
import android.view.inputmethod.InputMethodSubtype
@ -59,20 +56,9 @@ import androidx.savedstate.SavedStateRegistryOwner
import androidx.savedstate.findViewTreeSavedStateRegistryOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import org.futo.inputmethod.latin.common.Constants
import org.futo.inputmethod.latin.common.ComposedData
import org.futo.inputmethod.latin.uix.Action
import org.futo.inputmethod.latin.uix.ActionBar
import org.futo.inputmethod.latin.uix.ActionInputTransaction
@ -83,7 +69,6 @@ import org.futo.inputmethod.latin.uix.DynamicThemeProviderOwner
import org.futo.inputmethod.latin.uix.KeyboardManagerForAction
import org.futo.inputmethod.latin.uix.PersistentActionState
import org.futo.inputmethod.latin.uix.THEME_KEY
import org.futo.inputmethod.latin.uix.actions.VoiceInputAction
import org.futo.inputmethod.latin.uix.createInlineSuggestionsRequest
import org.futo.inputmethod.latin.uix.deferGetSetting
import org.futo.inputmethod.latin.uix.deferSetSetting
@ -94,14 +79,8 @@ import org.futo.inputmethod.latin.uix.theme.ThemeOption
import org.futo.inputmethod.latin.uix.theme.ThemeOptions
import org.futo.inputmethod.latin.uix.theme.Typography
import org.futo.inputmethod.latin.uix.theme.UixThemeWrapper
import org.futo.inputmethod.latin.uix.theme.presets.ClassicMaterialDark
import org.futo.inputmethod.latin.uix.theme.presets.DynamicSystemTheme
import org.futo.inputmethod.latin.uix.theme.presets.VoiceInputTheme
import org.futo.inputmethod.latin.settings.SettingsValues;
import org.futo.inputmethod.latin.settings.SettingsValuesForSuggestion
import org.futo.inputmethod.latin.xlm.LanguageModel;
import org.futo.inputmethod.latin.xlm.LanguageModelFacilitator;
import org.futo.inputmethod.latin.utils.SuggestionResults
import org.futo.inputmethod.latin.xlm.LanguageModelFacilitator
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner,
LatinIMELegacy.SuggestionStripController, DynamicThemeProviderOwner, KeyboardManagerForAction {
@ -688,6 +667,10 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
latinIMELegacy.mInputLogic.mConnection.commitText(v, 1)
}
override fun backspace(amount: Int) {
latinIMELegacy.mInputLogic.mConnection.deleteTextBeforeCursor(amount)
}
override fun closeActionWindow() {
if(currWindowActionWindow == null) return
returnBackToMainKeyboardViewFromAction()

View File

@ -3,7 +3,6 @@ package org.futo.inputmethod.latin.uix
import android.content.Context
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.material3.ColorScheme
import androidx.compose.runtime.Composable
import androidx.lifecycle.LifecycleCoroutineScope
import org.futo.inputmethod.latin.uix.theme.ThemeOption
@ -23,6 +22,7 @@ interface KeyboardManagerForAction {
fun createInputTransaction(applySpaceIfNeeded: Boolean): ActionInputTransaction
fun typeText(v: String)
fun backspace(amount: Int)
fun closeActionWindow()

View File

@ -2,8 +2,6 @@ package org.futo.inputmethod.latin.uix
import android.os.Build
import android.view.View
import android.view.inputmethod.InlineSuggestion
import androidx.annotation.RequiresApi
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
@ -14,9 +12,7 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ColorScheme
import androidx.compose.material3.Icon
@ -39,11 +35,10 @@ import androidx.compose.ui.draw.rotate
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.drawscope.scale
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@ -60,12 +55,12 @@ import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.flow.Flow
import org.futo.inputmethod.latin.R
import org.futo.inputmethod.latin.SuggestedWords
import org.futo.inputmethod.latin.SuggestedWords.SuggestedWordInfo
import org.futo.inputmethod.latin.SuggestedWords.SuggestedWordInfo.KIND_TYPED
import org.futo.inputmethod.latin.suggestions.SuggestionStripView
import org.futo.inputmethod.latin.uix.actions.EmojiAction
import org.futo.inputmethod.latin.uix.actions.ThemeAction
import org.futo.inputmethod.latin.uix.actions.VoiceInputAction
import org.futo.inputmethod.latin.uix.theme.DarkColorScheme
@ -319,6 +314,7 @@ fun ActionItemSmall(action: Action, onSelect: (Action) -> Unit) {
@Composable
fun RowScope.ActionItems(onSelect: (Action) -> Unit) {
ActionItem(EmojiAction, onSelect)
ActionItem(VoiceInputAction, onSelect)
ActionItem(ThemeAction, onSelect)

View File

@ -0,0 +1,168 @@
package org.futo.inputmethod.latin.uix.actions
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import org.futo.inputmethod.latin.R
import org.futo.inputmethod.latin.uix.Action
import org.futo.inputmethod.latin.uix.ActionWindow
data class EmojiItem(
val emoji: String,
val description: String,
val category: String
)
@Composable
fun EmojiGrid(onClick: (EmojiItem) -> Unit, onExit: () -> Unit, onBackspace: () -> Unit, onSpace: () -> Unit) {
val context = LocalContext.current
val emojis = remember {
val stream = context.resources.openRawResource(R.raw.gemoji)
val text = stream.bufferedReader().readText()
val emojidata = Json.parseToJsonElement(text)
emojidata.jsonArray.map {
EmojiItem(
emoji = it.jsonObject["emoji"]!!.jsonPrimitive.content,
description = it.jsonObject["description"]!!.jsonPrimitive.content,
category = it.jsonObject["category"]!!.jsonPrimitive.content,
)
}
}
val spToDp = context.resources.displayMetrics.scaledDensity / context.resources.displayMetrics.density
Column {
LazyVerticalGrid(
columns = GridCells.Adaptive((40.sp * spToDp).value.dp),
contentPadding = PaddingValues(10.dp),
modifier = Modifier.weight(1.0f)
) {
items(emojis) { emoji ->
Box(modifier = Modifier.fillMaxSize().clickable {
onClick(emoji)
}) {
Text(
text = emoji.emoji,
fontSize = 24.sp,
modifier = Modifier.align(Alignment.Center)
)
}
}
}
Surface(color = MaterialTheme.colorScheme.background, modifier = Modifier.fillMaxWidth().height(48.dp)) {
Row(modifier = Modifier.padding(2.dp, 8.dp, 2.dp, 0.dp)) {
IconButton(onClick = { onExit() }) {
Text("ABC", fontSize = 14.sp)
}
Button(onClick = { onSpace() }, modifier = Modifier.weight(1.0f).padding(8.dp, 2.dp), colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.outline.copy(alpha = 0.33f),
contentColor = MaterialTheme.colorScheme.onBackground,
disabledContainerColor = MaterialTheme.colorScheme.outline,
disabledContentColor = MaterialTheme.colorScheme.onBackground,
), shape = RoundedCornerShape(32.dp)) {
Text("")
}
IconButton(onClick = { onBackspace() }) {
val icon = painterResource(id = R.drawable.delete)
val iconColor = MaterialTheme.colorScheme.onBackground
Canvas(modifier = Modifier.fillMaxSize()) {
translate(
left = this.size.width / 2.0f - icon.intrinsicSize.width / 2.0f,
top = this.size.height / 2.0f - icon.intrinsicSize.height / 2.0f
) {
with(icon) {
draw(
icon.intrinsicSize,
colorFilter = androidx.compose.ui.graphics.ColorFilter.tint(
iconColor
)
)
}
}
}
}
}
}
}
}
@Preview(showBackground = true)
@Composable
fun EmojiGridPreview() {
EmojiGrid(
onBackspace = {},
onClick = {},
onExit = {},
onSpace = {}
)
}
val EmojiAction = Action(
icon = R.drawable.smile,
name = R.string.title_emojis,
simplePressImpl = null,
windowImpl = { manager, _ ->
object : ActionWindow {
@Composable
override fun windowName(): String {
return stringResource(R.string.title_emojis)
}
@Composable
override fun WindowContents() {
EmojiGrid(onClick = {
manager.typeText(it.emoji)
}, onExit = {
manager.closeActionWindow()
}, onSpace = {
manager.typeText(" ")
}, onBackspace = {
manager.backspace(1)
})
}
override fun close() {
}
}
}
)

View File

@ -59,13 +59,6 @@ fun HomeScreen(navController: NavHostController = rememberNavController()) {
icon = painterResource(id = R.drawable.eye)
)
NavigationItem(
title = "Training",
style = NavigationItemStyle.HomeTertiary,
navigate = { navController.navigate("trainDev") },
icon = painterResource(id = R.drawable.delete)
)
/*
NavigationItem(
title = "Advanced",

View File

@ -4,6 +4,7 @@ import android.content.Intent
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.booleanResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.NavHostController
@ -17,6 +18,7 @@ import org.futo.inputmethod.latin.uix.settings.ScreenTitle
import org.futo.inputmethod.latin.uix.settings.ScrollableList
import org.futo.inputmethod.latin.uix.settings.SettingToggleSharedPrefs
import org.futo.inputmethod.latin.uix.settings.Tip
import org.futo.inputmethod.latin.uix.settings.useSharedPrefsBool
@Preview
@Composable
@ -25,13 +27,26 @@ fun PredictiveTextScreen(navController: NavHostController = rememberNavControlle
ScrollableList {
ScreenTitle("Predictive Text", showBack = true, navController)
val (transformerLmEnabled, _) = useSharedPrefsBool(Settings.PREF_KEY_USE_TRANSFORMER_LM, true)
SettingToggleSharedPrefs(
title = "Transformer LM",
key = Settings.PREF_KEY_USE_TRANSFORMER_LM,
default = true
)
Tip("Note: Transformer LM is in alpha state")
if(transformerLmEnabled) {
NavigationItem(
title = "Training",
style = NavigationItemStyle.HomeTertiary,
navigate = { navController.navigate("trainDev") },
icon = painterResource(id = R.drawable.cpu)
)
Tip("Note: Transformer LM is in alpha state")
}
// TODO: It doesn't make a lot of sense in the case of having autocorrect on but show_suggestions off
@ -49,36 +64,36 @@ fun PredictiveTextScreen(navController: NavHostController = rememberNavControlle
default = true
)
Tip("Many of the below options currently have no effect if Transformer LM is enabled")
if(!transformerLmEnabled) {
NavigationItem(
title = stringResource(R.string.edit_personal_dictionary),
style = NavigationItemStyle.Misc,
navigate = {
val intent = Intent("android.settings.USER_DICTIONARY_SETTINGS")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent)
}
)
NavigationItem(
title = stringResource(R.string.edit_personal_dictionary),
style = NavigationItemStyle.Misc,
navigate = {
val intent = Intent("android.settings.USER_DICTIONARY_SETTINGS")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent)
}
)
NavigationItem(
title = stringResource(R.string.configure_dictionaries_title),
style = NavigationItemStyle.Misc,
navigate = {
val intent = Intent()
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.setClass(context, DictionarySettingsActivity::class.java)
intent.putExtra("clientId", "org.futo.inputmethod.latin")
context.startActivity(intent)
}
)
NavigationItem(
title = stringResource(R.string.configure_dictionaries_title),
style = NavigationItemStyle.Misc,
navigate = {
val intent = Intent()
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.setClass(context, DictionarySettingsActivity::class.java)
intent.putExtra("clientId", "org.futo.inputmethod.latin")
context.startActivity(intent)
}
)
SettingToggleSharedPrefs(
title = stringResource(R.string.prefs_block_potentially_offensive_title),
subtitle = stringResource(R.string.prefs_block_potentially_offensive_summary),
key = Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE,
default = booleanResource(R.bool.config_block_potentially_offensive)
)
SettingToggleSharedPrefs(
title = stringResource(R.string.prefs_block_potentially_offensive_title),
subtitle = stringResource(R.string.prefs_block_potentially_offensive_summary),
key = Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE,
default = booleanResource(R.bool.config_block_potentially_offensive)
)
}
SettingToggleSharedPrefs(
title = stringResource(R.string.use_personalized_dicts),
@ -87,11 +102,13 @@ fun PredictiveTextScreen(navController: NavHostController = rememberNavControlle
default = true
)
SettingToggleSharedPrefs(
title = stringResource(R.string.bigram_prediction),
subtitle = stringResource(R.string.bigram_prediction_summary),
key = Settings.PREF_BIGRAM_PREDICTIONS,
default = booleanResource(R.bool.config_default_next_word_prediction)
)
if(!transformerLmEnabled) {
SettingToggleSharedPrefs(
title = stringResource(R.string.bigram_prediction),
subtitle = stringResource(R.string.bigram_prediction_summary),
key = Settings.PREF_BIGRAM_PREDICTIONS,
default = booleanResource(R.bool.config_default_next_word_prediction)
)
}
}
}