mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Add basic emoji search using string matching
This commit is contained in:
parent
b6206e3059
commit
e181717692
@ -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? {
|
||||
return overrideInputConnection ?: super.getCurrentInputConnection()
|
||||
}
|
||||
|
||||
override fun getCurrentInputEditorInfo(): EditorInfo? {
|
||||
return overrideEditorInfo ?: super.getCurrentInputEditorInfo()
|
||||
}
|
||||
|
||||
fun getBaseInputConnection(): InputConnection? {
|
||||
return super.getCurrentInputConnection()
|
||||
}
|
||||
|
||||
override val lifecycle: Lifecycle
|
||||
get() = mLifecycleRegistry
|
||||
override val savedStateRegistry: SavedStateRegistry
|
||||
|
@ -3,6 +3,7 @@ package org.futo.inputmethod.latin.uix
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputConnection
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
@ -56,7 +57,7 @@ interface KeyboardManagerForAction {
|
||||
fun announce(s: String)
|
||||
fun getActiveLocale(): Locale
|
||||
|
||||
fun overrideInputConnection(inputConnection: InputConnection)
|
||||
fun overrideInputConnection(inputConnection: InputConnection, editorInfo: EditorInfo)
|
||||
fun unsetInputConnection()
|
||||
|
||||
fun requestDialog(text: String, options: List<DialogRequestItem>, onCancel: () -> Unit)
|
||||
|
@ -1,22 +1,21 @@
|
||||
package org.futo.inputmethod.latin.uix
|
||||
|
||||
import android.content.Context
|
||||
import android.text.InputType
|
||||
import android.util.AttributeSet
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputConnection
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
|
||||
|
||||
class ActionEditText(context: Context, val textChanged: (String) -> Unit) :
|
||||
class ActionEditText(context: Context) :
|
||||
androidx.appcompat.widget.AppCompatEditText(context) {
|
||||
var inputConnection: InputConnection? = null
|
||||
private set
|
||||
@ -26,6 +25,13 @@ class ActionEditText(context: Context, val textChanged: (String) -> Unit) :
|
||||
return inputConnection
|
||||
}
|
||||
|
||||
private var textChanged: (String) -> Unit = { }
|
||||
fun setTextChangeCallback(
|
||||
textChanged: (String) -> Unit
|
||||
) {
|
||||
this.textChanged = textChanged
|
||||
}
|
||||
|
||||
override fun onTextChanged(
|
||||
text: CharSequence?,
|
||||
start: Int,
|
||||
@ -33,7 +39,12 @@ class ActionEditText(context: Context, val textChanged: (String) -> Unit) :
|
||||
lengthAfter: Int
|
||||
) {
|
||||
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 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(
|
||||
factory = {
|
||||
ActionEditText(context) {
|
||||
text.value = it
|
||||
}.apply {
|
||||
onCreateInputConnection(
|
||||
EditorInfo()
|
||||
)
|
||||
ActionEditText(context).apply {
|
||||
this.inputType = inputType
|
||||
|
||||
setTextChangeCallback { text.value = it }
|
||||
|
||||
setText(text.value)
|
||||
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
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
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp),
|
||||
.fillMaxHeight(),
|
||||
onRelease = {
|
||||
manager.unsetInputConnection()
|
||||
}
|
||||
|
@ -36,4 +36,8 @@ object EmojiTracker {
|
||||
.filter { it.isNotBlank() }
|
||||
.distinct()
|
||||
}
|
||||
|
||||
suspend fun Context.resetRecentEmojis() {
|
||||
setSetting(lastUsedEmoji, "")
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import android.os.Vibrator
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InlineSuggestionsResponse
|
||||
import android.view.inputmethod.InputConnection
|
||||
import android.view.inputmethod.InputContentInfo
|
||||
@ -146,7 +147,11 @@ class UixActionKeyboardManager(val uixManager: UixManager, val latinIME: LatinIM
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -224,16 +229,13 @@ class UixActionKeyboardManager(val uixManager: UixManager, val latinIME: LatinIM
|
||||
return latinIME.latinIMELegacy.locale
|
||||
}
|
||||
|
||||
override fun overrideInputConnection(inputConnection: InputConnection) {
|
||||
latinIME.overrideInputConnection = inputConnection
|
||||
latinIME.inputLogic.startInput(RichInputMethodManager.getInstance().combiningRulesExtraValueOfCurrentSubtype,
|
||||
latinIME.latinIMELegacy.mSettings.current)
|
||||
override fun overrideInputConnection(inputConnection: InputConnection, editorInfo: EditorInfo) {
|
||||
latinIME.overrideInputConnection(inputConnection, editorInfo)
|
||||
uixManager.toggleExpandAction(true)
|
||||
}
|
||||
|
||||
override fun unsetInputConnection() {
|
||||
latinIME.overrideInputConnection = null
|
||||
latinIME.inputLogic.startInput(RichInputMethodManager.getInstance().combiningRulesExtraValueOfCurrentSubtype,
|
||||
latinIME.latinIMELegacy.mSettings.current)
|
||||
latinIME.overrideInputConnection(null, null)
|
||||
}
|
||||
|
||||
override fun requestDialog(text: String, options: List<DialogRequestItem>, onCancel: () -> Unit) {
|
||||
@ -361,8 +363,8 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
keyboardManagerForAction.announce("$name closed")
|
||||
}
|
||||
|
||||
private fun toggleExpandAction() {
|
||||
mainKeyboardHidden = !mainKeyboardHidden
|
||||
fun toggleExpandAction(to: Boolean? = null) {
|
||||
mainKeyboardHidden = !(to ?: mainKeyboardHidden)
|
||||
if(!mainKeyboardHidden) {
|
||||
latinIME.onKeyboardShown()
|
||||
}
|
||||
@ -378,7 +380,7 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
1.5
|
||||
}
|
||||
Column {
|
||||
if(mainKeyboardHidden) {
|
||||
if(mainKeyboardHidden || latinIME.isInputConnectionOverridden) {
|
||||
ActionWindowBar(
|
||||
onBack = { returnBackToMainKeyboardViewFromAction() },
|
||||
canExpand = currWindowAction!!.canShowKeyboard,
|
||||
@ -398,7 +400,7 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
windowImpl.WindowContents(keyboardShown = !isMainKeyboardHidden)
|
||||
}
|
||||
|
||||
if(!mainKeyboardHidden) {
|
||||
if(!mainKeyboardHidden && !latinIME.isInputConnectionOverridden) {
|
||||
val suggestedWordsOrNull = if (shouldShowSuggestionStrip) {
|
||||
suggestedWords
|
||||
} else {
|
||||
|
@ -11,9 +11,11 @@ import androidx.annotation.UiThread
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.absoluteOffset
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
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.rememberLazyListState
|
||||
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.IconButton
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
@ -43,6 +47,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
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.sp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -88,9 +95,12 @@ import kotlinx.serialization.json.jsonPrimitive
|
||||
import org.futo.inputmethod.latin.R
|
||||
import org.futo.inputmethod.latin.common.Constants
|
||||
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.AutoFitText
|
||||
import org.futo.inputmethod.latin.uix.DialogRequestItem
|
||||
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.PersistentActionState
|
||||
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_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
|
||||
class EmojiGridAdapter(
|
||||
private val data: List<EmojiViewItem>,
|
||||
private val onClick: (EmojiItem) -> Unit,
|
||||
private val onSelectSkinTone: (PopupInfo) -> Unit,
|
||||
private val emojiCellWidth: Int,
|
||||
private val contentColor: Color
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
) : ListAdapter<EmojiViewItem, RecyclerView.ViewHolder>(EmojiViewItemDiffCallback) {
|
||||
|
||||
class EmojiViewHolder(
|
||||
context: Context,
|
||||
@ -189,7 +209,7 @@ class EmojiGridAdapter(
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val item = data[position]
|
||||
val item = getItem(position)
|
||||
if(item is EmojiItemItem && holder is EmojiViewHolder) {
|
||||
holder.bindEmoji(item.emoji, onClick, onSelectSkinTone, contentColor.toArgb())
|
||||
}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 {
|
||||
return when(data[position]) {
|
||||
return when(getItem(position)) {
|
||||
is CategoryItem -> VIEW_CATEGORY
|
||||
is EmojiItemItem -> VIEW_EMOJI
|
||||
}
|
||||
@ -259,7 +277,6 @@ fun Emojis(
|
||||
|
||||
val emojiAdapter = remember {
|
||||
EmojiGridAdapter(
|
||||
emojis,
|
||||
onClick,
|
||||
onSelectSkinTone = {
|
||||
activePopup = it
|
||||
@ -270,6 +287,10 @@ fun Emojis(
|
||||
)
|
||||
}
|
||||
|
||||
LaunchedEffect(emojis) {
|
||||
emojiAdapter.submitList(emojis)
|
||||
}
|
||||
|
||||
var viewWidth by remember { mutableIntStateOf(0) }
|
||||
var viewHeight by remember { mutableIntStateOf(0) }
|
||||
var popupSize by remember { mutableStateOf(IntSize(0, 0)) }
|
||||
@ -281,13 +302,14 @@ fun Emojis(
|
||||
layoutManager = GridLayoutManager(context, 8).apply {
|
||||
spanSizeLookup = object : SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return when(emojis[position]) {
|
||||
return when(emojiAdapter.currentList[position]) {
|
||||
is EmojiItemItem -> 1
|
||||
is CategoryItem -> spanCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adapter = emojiAdapter
|
||||
|
||||
addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
@ -566,7 +588,9 @@ fun EmojiGrid(
|
||||
emojis: List<EmojiItem>,
|
||||
keyboardShown: Boolean,
|
||||
emojiMap: Map<String, EmojiItem>,
|
||||
keyBackground: Drawable
|
||||
keyBackground: Drawable,
|
||||
isSearching: Boolean,
|
||||
searchFilter: String
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val recentEmojis = remember {
|
||||
@ -596,6 +620,23 @@ fun EmojiGrid(
|
||||
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 {
|
||||
Emojis(
|
||||
modifier = Modifier
|
||||
@ -612,25 +653,27 @@ fun EmojiGrid(
|
||||
keyBackground.state = intArrayOf()
|
||||
keyBackground.draw(this.drawContext.canvas.nativeCanvas)
|
||||
},
|
||||
emojis = listOf(CategoryItem("Recent")) + recentEmojis.map { EmojiItemItem(it) } + categorizedEmojis,
|
||||
emojis = emojiList,
|
||||
onClick = onClick,
|
||||
emojiMap = emojiMap,
|
||||
currentCategory = currentCategory,
|
||||
jumpCategory = jumpCategory
|
||||
)
|
||||
|
||||
EmojiNavigation(
|
||||
showKeys = !keyboardShown,
|
||||
onExit = onExit,
|
||||
onBackspace = onBackspace,
|
||||
categories = listOf(
|
||||
CategoryItem("Recent")
|
||||
) + categorizedEmojis.filterIsInstance<CategoryItem>(),
|
||||
activeCategoryItem = currentCategory.value,
|
||||
goToCategory = {
|
||||
jumpCategory.value = it
|
||||
}
|
||||
)
|
||||
if(!isSearching) {
|
||||
EmojiNavigation(
|
||||
showKeys = !keyboardShown,
|
||||
onExit = onExit,
|
||||
onBackspace = onBackspace,
|
||||
categories = listOf(
|
||||
CategoryItem("Recent")
|
||||
) + categorizedEmojis.filterIsInstance<CategoryItem>(),
|
||||
activeCategoryItem = currentCategory.value,
|
||||
goToCategory = {
|
||||
jumpCategory.value = it
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -719,6 +762,9 @@ val EmojiAction = Action(
|
||||
windowImpl = { manager, persistentState ->
|
||||
val state = persistentState as PersistentEmojiState
|
||||
object : ActionWindow {
|
||||
private val searchText = mutableStateOf("")
|
||||
private val searching = mutableStateOf(false)
|
||||
|
||||
@Composable
|
||||
override fun windowName(): String {
|
||||
return stringResource(R.string.emoji_action_title)
|
||||
@ -745,7 +791,67 @@ val EmojiAction = Action(
|
||||
if(!isRepeated) {
|
||||
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,
|
||||
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 = ""
|
||||
)
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class EmojiView @JvmOverloads constructor(
|
||||
View(context, attrs) {
|
||||
|
||||
companion object {
|
||||
private const val EMOJI_DRAW_TEXT_SIZE_SP = 32
|
||||
private const val EMOJI_DRAW_TEXT_SIZE_DP = 42
|
||||
}
|
||||
|
||||
init {
|
||||
@ -61,8 +61,8 @@ class EmojiView @JvmOverloads constructor(
|
||||
|
||||
private val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG).apply {
|
||||
textSize = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
EMOJI_DRAW_TEXT_SIZE_SP.toFloat(),
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
EMOJI_DRAW_TEXT_SIZE_DP.toFloat(),
|
||||
context.resources.displayMetrics
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user