Update inline suggestions

This commit is contained in:
Aleksandras Kostarevas 2024-05-27 18:32:01 +03:00
parent 4cc53b0efa
commit 562b08883b
4 changed files with 86 additions and 30 deletions

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#14000000">
<item android:shape="rectangle">
<shape>
<corners android:radius="32dp"/>
<stroke android:color="#99FFFFFF" android:width="2dp"/>
<solid android:color="#44FFFFFF"/>
</shape>
</item>
</ripple>

View File

@ -5,6 +5,8 @@ import android.os.Build
import android.view.View
import androidx.annotation.RequiresApi
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
@ -425,7 +427,8 @@ fun LazyItemScope.ActionItem(idx: Int, action: Action, onSelect: (Action) -> Uni
if (!dragging.value) {
it.animateItemPlacement()
} else {
it.zIndex(10.0f)
it
.zIndex(10.0f)
.graphicsLayer {
clip = false
translationX = offsetX.floatValue
@ -602,6 +605,12 @@ fun ActionBar(
}
}
LaunchedEffect(inlineSuggestions) {
if(inlineSuggestions.isNotEmpty()) {
isActionsOpen.value = false
}
}
Surface(modifier = Modifier
.fillMaxWidth()
.height(40.dp), color = MaterialTheme.colorScheme.background)
@ -624,9 +633,13 @@ fun ActionBar(
}
if(!isActionsOpen.value) {
if (inlineSuggestions.isNotEmpty() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
InlineSuggestions(inlineSuggestions)
} else if (words != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
AnimatedVisibility(inlineSuggestions.isNotEmpty(), enter = fadeIn(), exit = fadeOut()) {
InlineSuggestions(inlineSuggestions)
}
}
if (words != null && inlineSuggestions.isEmpty()) {
SuggestionItems(
words,
onClick = {
@ -700,7 +713,6 @@ fun CollapsibleSuggestionsBar(
onCollapse: () -> Unit,
words: SuggestedWords?,
suggestionStripListener: SuggestionStripView.Listener,
inlineSuggestions: List<MutableState<View?>>,
) {
Surface(modifier = Modifier
.fillMaxWidth()
@ -726,9 +738,7 @@ fun CollapsibleSuggestionsBar(
)
}
if(inlineSuggestions.isNotEmpty() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
InlineSuggestions(inlineSuggestions)
} else if(words != null) {
if(words != null) {
SuggestionItems(words, onClick = {
suggestionStripListener.pickSuggestionManually(
words.getInfo(it)
@ -879,8 +889,7 @@ fun PreviewCollapsibleBar(colorScheme: ColorScheme = DarkColorScheme) {
onCollapse = { },
onClose = { },
words = exampleSuggestedWords,
suggestionStripListener = ExampleListener(),
inlineSuggestions = listOf()
suggestionStripListener = ExampleListener()
)
}

View File

@ -2,8 +2,10 @@ package org.futo.inputmethod.latin.uix
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.drawable.Icon
import android.os.Build
import android.util.Size
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InlineSuggestion
@ -15,20 +17,35 @@ import androidx.autofill.inline.common.ImageViewStyle
import androidx.autofill.inline.common.TextViewStyle
import androidx.autofill.inline.common.ViewStyle
import androidx.autofill.inline.v1.InlineSuggestionUi
import androidx.compose.foundation.clipScrollableContainer
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material3.ColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import org.futo.inputmethod.latin.R
import kotlin.math.roundToInt
private const val maxSuggestions = 5
private const val minWidthDp = 32.0f
private const val minHeightDp = 8.0f
private const val maxHeightDp = 48.0f
@SuppressLint("RestrictedApi")
@RequiresApi(Build.VERSION_CODES.R)
fun createInlineSuggestionsRequest(
@ -39,17 +56,24 @@ fun createInlineSuggestionsRequest(
context.fromDp(v).roundToInt()
}
val drawable = R.drawable.inline_suggestion_chip
val bgColor = activeColorScheme.secondaryContainer.toArgb()
val stylesBuilder = UiVersions.newStylesBuilder()
val suggestionStyle = InlineSuggestionUi.newStyleBuilder()
.setSingleIconChipStyle(
ViewStyle.Builder()
.setBackgroundColor(activeColorScheme.secondaryContainer.toArgb())
.setBackground(
Icon.createWithResource(context, drawable).setTint(bgColor)
)
.setPadding(0, 0, 0, 0)
.build()
)
.setChipStyle(
ViewStyle.Builder()
.setBackgroundColor(activeColorScheme.secondaryContainer.toArgb())
.setBackground(
Icon.createWithResource(context, drawable).setTint(bgColor)
)
.setPadding(
fromDp(8.0f),
fromDp(0.0f),
@ -93,13 +117,23 @@ fun createInlineSuggestionsRequest(
val stylesBundle = stylesBuilder.build()
val displayMetrics = context.resources.displayMetrics
val maxWidthPx = displayMetrics.widthPixels * 2 / 3
val spec = InlinePresentationSpec.Builder(
Size(0, 0),
Size(Int.MAX_VALUE, Int.MAX_VALUE)
Size(
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, minWidthDp, displayMetrics).roundToInt(),
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, minHeightDp, displayMetrics).roundToInt()
),
Size(
maxWidthPx,
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, maxHeightDp, displayMetrics).roundToInt()
),
).setStyle(stylesBundle).build()
return InlineSuggestionsRequest.Builder(listOf(spec)).let { request ->
request.setMaxSuggestionCount(InlineSuggestionsRequest.SUGGESTION_COUNT_UNLIMITED)
return InlineSuggestionsRequest.Builder(List(maxSuggestions) { spec }).let { request ->
request.setMaxSuggestionCount(maxSuggestions)
request.build()
}
}
@ -126,24 +160,26 @@ fun Context.inflateInlineSuggestion(inlineSuggestion: InlineSuggestion): Mutable
@RequiresApi(Build.VERSION_CODES.R)
@Composable
fun InlineSuggestionView(inlineSuggestion: MutableState<View?>) {
if (inlineSuggestion.value != null) {
// TODO: For some reason this appears over top of keyboard key previews
// We should also make it animate in and round corners
AndroidView(
factory = { inlineSuggestion.value!! },
modifier = Modifier.padding(4.dp, 0.dp)
)
key(inlineSuggestion.value) {
if (inlineSuggestion.value != null) {
AndroidView(
factory = { inlineSuggestion.value!! },
modifier = Modifier.padding(4.dp, 0.dp)
)
}
}
}
@RequiresApi(Build.VERSION_CODES.R)
@Composable
fun RowScope.InlineSuggestions(suggestions: List<MutableState<View?>>) {
LazyRow(modifier = Modifier
val scrollState = rememberScrollState()
Row(modifier = Modifier
.weight(1.0f)
.padding(0.dp, 4.dp)) {
items(suggestions.size) {
InlineSuggestionView(suggestions[it])
}
.padding(0.dp, 4.dp)
.horizontalScroll(scrollState)
.clipScrollableContainer(Orientation.Horizontal)
.clipToBounds()) {
suggestions.forEach { InlineSuggestionView(it) }
}
}

View File

@ -328,8 +328,7 @@ class UixManager(private val latinIME: LatinIME) {
onCollapse = { toggleExpandAction() },
onClose = { returnBackToMainKeyboardViewFromAction() },
words = suggestedWordsOrNull,
suggestionStripListener = latinIME.latinIMELegacy as SuggestionStripView.Listener,
inlineSuggestions = inlineSuggestions
suggestionStripListener = latinIME.latinIMELegacy as SuggestionStripView.Listener
)
}
}