Add basic emoji search using string matching

This commit is contained in:
Aleksandras Kostarevas 2024-07-13 12:41:42 +03:00
parent b6206e3059
commit e181717692
7 changed files with 225 additions and 55 deletions

View File

@ -678,11 +678,40 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
} }
} }
var overrideInputConnection: InputConnection? = null private var overrideInputConnection: InputConnection? = null
private var overrideEditorInfo: EditorInfo? = null
fun overrideInputConnection(to: InputConnection?, editorInfo: EditorInfo?) {
this.overrideInputConnection = to
this.overrideEditorInfo = editorInfo
latinIMELegacy.loadSettings()
inputLogic.finishInput()
inputLogic.startInput(RichInputMethodManager.getInstance().combiningRulesExtraValueOfCurrentSubtype, latinIMELegacy.mSettings.current)
val currentIC = currentInputConnection
currentIC?.requestCursorUpdates(InputConnection.CURSOR_UPDATE_IMMEDIATE)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
super.getCurrentInputConnection()?.setImeConsumesInput(to != null)
}
}
val isInputConnectionOverridden
get() = overrideInputConnection != null
override fun getCurrentInputConnection(): InputConnection? { override fun getCurrentInputConnection(): InputConnection? {
return overrideInputConnection ?: super.getCurrentInputConnection() return overrideInputConnection ?: super.getCurrentInputConnection()
} }
override fun getCurrentInputEditorInfo(): EditorInfo? {
return overrideEditorInfo ?: super.getCurrentInputEditorInfo()
}
fun getBaseInputConnection(): InputConnection? {
return super.getCurrentInputConnection()
}
override val lifecycle: Lifecycle override val lifecycle: Lifecycle
get() = mLifecycleRegistry get() = mLifecycleRegistry
override val savedStateRegistry: SavedStateRegistry override val savedStateRegistry: SavedStateRegistry

View File

@ -3,6 +3,7 @@ package org.futo.inputmethod.latin.uix
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import android.view.View import android.view.View
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection import android.view.inputmethod.InputConnection
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
@ -56,7 +57,7 @@ interface KeyboardManagerForAction {
fun announce(s: String) fun announce(s: String)
fun getActiveLocale(): Locale fun getActiveLocale(): Locale
fun overrideInputConnection(inputConnection: InputConnection) fun overrideInputConnection(inputConnection: InputConnection, editorInfo: EditorInfo)
fun unsetInputConnection() fun unsetInputConnection()
fun requestDialog(text: String, options: List<DialogRequestItem>, onCancel: () -> Unit) fun requestDialog(text: String, options: List<DialogRequestItem>, onCancel: () -> Unit)

View File

@ -1,22 +1,21 @@
package org.futo.inputmethod.latin.uix package org.futo.inputmethod.latin.uix
import android.content.Context import android.content.Context
import android.text.InputType
import android.util.AttributeSet
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection import android.view.inputmethod.InputConnection
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
class ActionEditText(context: Context, val textChanged: (String) -> Unit) : class ActionEditText(context: Context) :
androidx.appcompat.widget.AppCompatEditText(context) { androidx.appcompat.widget.AppCompatEditText(context) {
var inputConnection: InputConnection? = null var inputConnection: InputConnection? = null
private set private set
@ -26,6 +25,13 @@ class ActionEditText(context: Context, val textChanged: (String) -> Unit) :
return inputConnection return inputConnection
} }
private var textChanged: (String) -> Unit = { }
fun setTextChangeCallback(
textChanged: (String) -> Unit
) {
this.textChanged = textChanged
}
override fun onTextChanged( override fun onTextChanged(
text: CharSequence?, text: CharSequence?,
start: Int, start: Int,
@ -33,7 +39,12 @@ class ActionEditText(context: Context, val textChanged: (String) -> Unit) :
lengthAfter: Int lengthAfter: Int
) { ) {
super.onTextChanged(text, start, lengthBefore, lengthAfter) super.onTextChanged(text, start, lengthBefore, lengthAfter)
textChanged(text?.toString() ?: "")
// For some strange reason this IS null sometimes, even though it
// shouldn't be
if(textChanged != null) {
textChanged(text?.toString() ?: "")
}
} }
} }
@ -43,26 +54,41 @@ fun ActionTextEditor(text: MutableState<String>) {
val context = LocalContext.current val context = LocalContext.current
val manager = LocalManager.current val manager = LocalManager.current
val height = with(LocalDensity.current) {
48.dp.toPx()
}
val inputType = EditorInfo.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE or EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS
AndroidView( AndroidView(
factory = { factory = {
ActionEditText(context) { ActionEditText(context).apply {
text.value = it this.inputType = inputType
}.apply {
onCreateInputConnection( setTextChangeCallback { text.value = it }
EditorInfo()
) setText(text.value)
layoutParams = ViewGroup.LayoutParams( layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT ViewGroup.LayoutParams.WRAP_CONTENT
) )
inputType = InputType.TYPE_CLASS_TEXT
manager.overrideInputConnection(inputConnection!!) setHeight(height.toInt())
val editorInfo = EditorInfo().apply {
this.inputType = inputType
}
onCreateInputConnection(editorInfo)
manager.overrideInputConnection(inputConnection!!, editorInfo)
requestFocus()
} }
}, },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(16.dp), .fillMaxHeight(),
onRelease = { onRelease = {
manager.unsetInputConnection() manager.unsetInputConnection()
} }

View File

@ -36,4 +36,8 @@ object EmojiTracker {
.filter { it.isNotBlank() } .filter { it.isNotBlank() }
.distinct() .distinct()
} }
suspend fun Context.resetRecentEmojis() {
setSetting(lastUsedEmoji, "")
}
} }

View File

@ -11,6 +11,7 @@ import android.os.Vibrator
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InlineSuggestionsResponse import android.view.inputmethod.InlineSuggestionsResponse
import android.view.inputmethod.InputConnection import android.view.inputmethod.InputConnection
import android.view.inputmethod.InputContentInfo import android.view.inputmethod.InputContentInfo
@ -146,7 +147,11 @@ class UixActionKeyboardManager(val uixManager: UixManager, val latinIME: LatinIM
} }
override fun typeText(v: String) { override fun typeText(v: String) {
latinIME.latinIMELegacy.onTextInput(v) if(latinIME.isInputConnectionOverridden) {
latinIME.getBaseInputConnection()?.commitText(v, 1)
} else {
latinIME.latinIMELegacy.onTextInput(v)
}
} }
override fun typeUri(uri: Uri, mimeTypes: List<String>): Boolean { override fun typeUri(uri: Uri, mimeTypes: List<String>): Boolean {
@ -224,16 +229,13 @@ class UixActionKeyboardManager(val uixManager: UixManager, val latinIME: LatinIM
return latinIME.latinIMELegacy.locale return latinIME.latinIMELegacy.locale
} }
override fun overrideInputConnection(inputConnection: InputConnection) { override fun overrideInputConnection(inputConnection: InputConnection, editorInfo: EditorInfo) {
latinIME.overrideInputConnection = inputConnection latinIME.overrideInputConnection(inputConnection, editorInfo)
latinIME.inputLogic.startInput(RichInputMethodManager.getInstance().combiningRulesExtraValueOfCurrentSubtype, uixManager.toggleExpandAction(true)
latinIME.latinIMELegacy.mSettings.current)
} }
override fun unsetInputConnection() { override fun unsetInputConnection() {
latinIME.overrideInputConnection = null latinIME.overrideInputConnection(null, null)
latinIME.inputLogic.startInput(RichInputMethodManager.getInstance().combiningRulesExtraValueOfCurrentSubtype,
latinIME.latinIMELegacy.mSettings.current)
} }
override fun requestDialog(text: String, options: List<DialogRequestItem>, onCancel: () -> Unit) { override fun requestDialog(text: String, options: List<DialogRequestItem>, onCancel: () -> Unit) {
@ -361,8 +363,8 @@ class UixManager(private val latinIME: LatinIME) {
keyboardManagerForAction.announce("$name closed") keyboardManagerForAction.announce("$name closed")
} }
private fun toggleExpandAction() { fun toggleExpandAction(to: Boolean? = null) {
mainKeyboardHidden = !mainKeyboardHidden mainKeyboardHidden = !(to ?: mainKeyboardHidden)
if(!mainKeyboardHidden) { if(!mainKeyboardHidden) {
latinIME.onKeyboardShown() latinIME.onKeyboardShown()
} }
@ -378,7 +380,7 @@ class UixManager(private val latinIME: LatinIME) {
1.5 1.5
} }
Column { Column {
if(mainKeyboardHidden) { if(mainKeyboardHidden || latinIME.isInputConnectionOverridden) {
ActionWindowBar( ActionWindowBar(
onBack = { returnBackToMainKeyboardViewFromAction() }, onBack = { returnBackToMainKeyboardViewFromAction() },
canExpand = currWindowAction!!.canShowKeyboard, canExpand = currWindowAction!!.canShowKeyboard,
@ -398,7 +400,7 @@ class UixManager(private val latinIME: LatinIME) {
windowImpl.WindowContents(keyboardShown = !isMainKeyboardHidden) windowImpl.WindowContents(keyboardShown = !isMainKeyboardHidden)
} }
if(!mainKeyboardHidden) { if(!mainKeyboardHidden && !latinIME.isInputConnectionOverridden) {
val suggestedWordsOrNull = if (shouldShowSuggestionStrip) { val suggestedWordsOrNull = if (shouldShowSuggestionStrip) {
suggestedWords suggestedWords
} else { } else {

View File

@ -11,9 +11,11 @@ import androidx.annotation.UiThread
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Canvas import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.absoluteOffset import androidx.compose.foundation.layout.absoluteOffset
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -25,6 +27,8 @@ import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalContentColor import androidx.compose.material3.LocalContentColor
@ -43,6 +47,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@ -73,8 +78,10 @@ import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -88,9 +95,12 @@ import kotlinx.serialization.json.jsonPrimitive
import org.futo.inputmethod.latin.R import org.futo.inputmethod.latin.R
import org.futo.inputmethod.latin.common.Constants import org.futo.inputmethod.latin.common.Constants
import org.futo.inputmethod.latin.uix.Action import org.futo.inputmethod.latin.uix.Action
import org.futo.inputmethod.latin.uix.ActionTextEditor
import org.futo.inputmethod.latin.uix.ActionWindow import org.futo.inputmethod.latin.uix.ActionWindow
import org.futo.inputmethod.latin.uix.AutoFitText import org.futo.inputmethod.latin.uix.AutoFitText
import org.futo.inputmethod.latin.uix.DialogRequestItem
import org.futo.inputmethod.latin.uix.EmojiTracker.getRecentEmojis import org.futo.inputmethod.latin.uix.EmojiTracker.getRecentEmojis
import org.futo.inputmethod.latin.uix.EmojiTracker.resetRecentEmojis
import org.futo.inputmethod.latin.uix.EmojiTracker.useEmoji import org.futo.inputmethod.latin.uix.EmojiTracker.useEmoji
import org.futo.inputmethod.latin.uix.PersistentActionState import org.futo.inputmethod.latin.uix.PersistentActionState
import org.futo.inputmethod.latin.uix.actions.emoji.EmojiItem import org.futo.inputmethod.latin.uix.actions.emoji.EmojiItem
@ -127,14 +137,24 @@ class EmojiItemItem(val emoji: EmojiItem) : EmojiViewItem() {
const val VIEW_EMOJI = 0 const val VIEW_EMOJI = 0
const val VIEW_CATEGORY = 1 const val VIEW_CATEGORY = 1
private object EmojiViewItemDiffCallback : DiffUtil.ItemCallback<EmojiViewItem>() {
override fun areItemsTheSame(oldItem: EmojiViewItem, newItem: EmojiViewItem): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: EmojiViewItem, newItem: EmojiViewItem): Boolean {
return oldItem == newItem
}
}
// Note: Using traditional View here, because Android Compose leaves a lot of performance to be desired // Note: Using traditional View here, because Android Compose leaves a lot of performance to be desired
class EmojiGridAdapter( class EmojiGridAdapter(
private val data: List<EmojiViewItem>,
private val onClick: (EmojiItem) -> Unit, private val onClick: (EmojiItem) -> Unit,
private val onSelectSkinTone: (PopupInfo) -> Unit, private val onSelectSkinTone: (PopupInfo) -> Unit,
private val emojiCellWidth: Int, private val emojiCellWidth: Int,
private val contentColor: Color private val contentColor: Color
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : ListAdapter<EmojiViewItem, RecyclerView.ViewHolder>(EmojiViewItemDiffCallback) {
class EmojiViewHolder( class EmojiViewHolder(
context: Context, context: Context,
@ -189,7 +209,7 @@ class EmojiGridAdapter(
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = data[position] val item = getItem(position)
if(item is EmojiItemItem && holder is EmojiViewHolder) { if(item is EmojiItemItem && holder is EmojiViewHolder) {
holder.bindEmoji(item.emoji, onClick, onSelectSkinTone, contentColor.toArgb()) holder.bindEmoji(item.emoji, onClick, onSelectSkinTone, contentColor.toArgb())
}else if(item is CategoryItem && holder is CategoryViewHolder) { }else if(item is CategoryItem && holder is CategoryViewHolder) {
@ -197,10 +217,8 @@ class EmojiGridAdapter(
} }
} }
override fun getItemCount() = data.size
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
return when(data[position]) { return when(getItem(position)) {
is CategoryItem -> VIEW_CATEGORY is CategoryItem -> VIEW_CATEGORY
is EmojiItemItem -> VIEW_EMOJI is EmojiItemItem -> VIEW_EMOJI
} }
@ -259,7 +277,6 @@ fun Emojis(
val emojiAdapter = remember { val emojiAdapter = remember {
EmojiGridAdapter( EmojiGridAdapter(
emojis,
onClick, onClick,
onSelectSkinTone = { onSelectSkinTone = {
activePopup = it activePopup = it
@ -270,6 +287,10 @@ fun Emojis(
) )
} }
LaunchedEffect(emojis) {
emojiAdapter.submitList(emojis)
}
var viewWidth by remember { mutableIntStateOf(0) } var viewWidth by remember { mutableIntStateOf(0) }
var viewHeight by remember { mutableIntStateOf(0) } var viewHeight by remember { mutableIntStateOf(0) }
var popupSize by remember { mutableStateOf(IntSize(0, 0)) } var popupSize by remember { mutableStateOf(IntSize(0, 0)) }
@ -281,13 +302,14 @@ fun Emojis(
layoutManager = GridLayoutManager(context, 8).apply { layoutManager = GridLayoutManager(context, 8).apply {
spanSizeLookup = object : SpanSizeLookup() { spanSizeLookup = object : SpanSizeLookup() {
override fun getSpanSize(position: Int): Int { override fun getSpanSize(position: Int): Int {
return when(emojis[position]) { return when(emojiAdapter.currentList[position]) {
is EmojiItemItem -> 1 is EmojiItemItem -> 1
is CategoryItem -> spanCount is CategoryItem -> spanCount
} }
} }
} }
} }
adapter = emojiAdapter adapter = emojiAdapter
addOnScrollListener(object : RecyclerView.OnScrollListener() { addOnScrollListener(object : RecyclerView.OnScrollListener() {
@ -566,7 +588,9 @@ fun EmojiGrid(
emojis: List<EmojiItem>, emojis: List<EmojiItem>,
keyboardShown: Boolean, keyboardShown: Boolean,
emojiMap: Map<String, EmojiItem>, emojiMap: Map<String, EmojiItem>,
keyBackground: Drawable keyBackground: Drawable,
isSearching: Boolean,
searchFilter: String
) { ) {
val context = LocalContext.current val context = LocalContext.current
val recentEmojis = remember { val recentEmojis = remember {
@ -596,6 +620,23 @@ fun EmojiGrid(
val jumpCategory: MutableState<CategoryItem?> = remember { mutableStateOf(null) } val jumpCategory: MutableState<CategoryItem?> = remember { mutableStateOf(null) }
var emojiList = listOf(CategoryItem("Recent")) + recentEmojis.map { EmojiItemItem(it) } + categorizedEmojis
if(isSearching) {
emojiList = emojiList.filter {
(it is EmojiItemItem) &&
(it.emoji.description.contains(searchFilter)
|| it.emoji.aliases.joinToString().contains(searchFilter)
|| it.emoji.tags.joinToString().contains(searchFilter))
}.take(48).map {
EmojiItemItem((it as EmojiItemItem).emoji.copy(category = "Search Results"))
}
if(emojiList.isEmpty()) {
emojiList = emojiList + listOf(CategoryItem("No results found"))
}
}
Column { Column {
Emojis( Emojis(
modifier = Modifier modifier = Modifier
@ -612,25 +653,27 @@ fun EmojiGrid(
keyBackground.state = intArrayOf() keyBackground.state = intArrayOf()
keyBackground.draw(this.drawContext.canvas.nativeCanvas) keyBackground.draw(this.drawContext.canvas.nativeCanvas)
}, },
emojis = listOf(CategoryItem("Recent")) + recentEmojis.map { EmojiItemItem(it) } + categorizedEmojis, emojis = emojiList,
onClick = onClick, onClick = onClick,
emojiMap = emojiMap, emojiMap = emojiMap,
currentCategory = currentCategory, currentCategory = currentCategory,
jumpCategory = jumpCategory jumpCategory = jumpCategory
) )
EmojiNavigation( if(!isSearching) {
showKeys = !keyboardShown, EmojiNavigation(
onExit = onExit, showKeys = !keyboardShown,
onBackspace = onBackspace, onExit = onExit,
categories = listOf( onBackspace = onBackspace,
CategoryItem("Recent") categories = listOf(
) + categorizedEmojis.filterIsInstance<CategoryItem>(), CategoryItem("Recent")
activeCategoryItem = currentCategory.value, ) + categorizedEmojis.filterIsInstance<CategoryItem>(),
goToCategory = { activeCategoryItem = currentCategory.value,
jumpCategory.value = it goToCategory = {
} jumpCategory.value = it
) }
)
}
} }
} }
@ -719,6 +762,9 @@ val EmojiAction = Action(
windowImpl = { manager, persistentState -> windowImpl = { manager, persistentState ->
val state = persistentState as PersistentEmojiState val state = persistentState as PersistentEmojiState
object : ActionWindow { object : ActionWindow {
private val searchText = mutableStateOf("")
private val searching = mutableStateOf(false)
@Composable @Composable
override fun windowName(): String { override fun windowName(): String {
return stringResource(R.string.emoji_action_title) return stringResource(R.string.emoji_action_title)
@ -745,7 +791,67 @@ val EmojiAction = Action(
if(!isRepeated) { if(!isRepeated) {
manager.performHapticAndAudioFeedback(Constants.CODE_DELETE, view) manager.performHapticAndAudioFeedback(Constants.CODE_DELETE, view)
} }
}, emojis = emojis, keyboardShown = keyboardShown, emojiMap = state.emojiMap, keyBackground = manager.getThemeProvider().keyBackground) }, emojis = emojis, keyboardShown = keyboardShown, emojiMap = state.emojiMap, keyBackground = manager.getThemeProvider().keyBackground,
isSearching = searching.value, searchFilter = searchText.value)
}
}
@Composable
override fun WindowTitleBar(rowScope: RowScope) {
if(searching.value) {
with(rowScope) {
Surface(
color = MaterialTheme.colorScheme.surfaceBright,
shape = RoundedCornerShape(24.dp),
modifier = Modifier
.minimumInteractiveComponentSize()
.padding(2.dp)
.weight(1.0f)
) {
Box(
modifier = Modifier.padding(8.dp),
contentAlignment = Alignment.CenterStart
) {
ActionTextEditor(text = searchText)
}
}
}
} else {
super.WindowTitleBar(rowScope)
Surface(color = MaterialTheme.colorScheme.surfaceBright, shape = RoundedCornerShape(24.dp), modifier = Modifier
.minimumInteractiveComponentSize()
.padding(2.dp)
.width(128.dp)
.clickable { searching.value = true }) {
Box(modifier = Modifier.padding(8.dp), contentAlignment = Alignment.CenterStart) {
Row {
Icon(Icons.Default.Search, contentDescription = null)
Text("Search", style = Typography.bodySmall, modifier = Modifier
.alpha(0.75f)
.align(Alignment.CenterVertically))
}
}
}
IconButton(onClick = {
manager.requestDialog(
"Clear recent emojis?",
listOf(
DialogRequestItem("Cancel") {},
DialogRequestItem("Clear") {
runBlocking {
manager.getContext().resetRecentEmojis()
}
manager.closeActionWindow()
},
),
{}
)
}) {
Icon(painterResource(id = R.drawable.close), contentDescription = "Clear recent emojis")
}
} }
} }
@ -772,6 +878,8 @@ fun EmojiGridPreview() {
}, },
keyboardShown = false, keyboardShown = false,
emojiMap = hashMapOf(), emojiMap = hashMapOf(),
keyBackground = context.getDrawable(R.drawable.btn_keyboard_spacebar_lxx_dark)!! keyBackground = context.getDrawable(R.drawable.btn_keyboard_spacebar_lxx_dark)!!,
isSearching = false,
searchFilter = ""
) )
} }

View File

@ -49,7 +49,7 @@ class EmojiView @JvmOverloads constructor(
View(context, attrs) { View(context, attrs) {
companion object { companion object {
private const val EMOJI_DRAW_TEXT_SIZE_SP = 32 private const val EMOJI_DRAW_TEXT_SIZE_DP = 42
} }
init { init {
@ -61,8 +61,8 @@ class EmojiView @JvmOverloads constructor(
private val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG).apply { private val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG).apply {
textSize = TypedValue.applyDimension( textSize = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, TypedValue.COMPLEX_UNIT_DIP,
EMOJI_DRAW_TEXT_SIZE_SP.toFloat(), EMOJI_DRAW_TEXT_SIZE_DP.toFloat(),
context.resources.displayMetrics context.resources.displayMetrics
) )
} }