mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Update inline suggestions
This commit is contained in:
parent
4cc53b0efa
commit
562b08883b
12
java/res/drawable/inline_suggestion_chip.xml
Normal file
12
java/res/drawable/inline_suggestion_chip.xml
Normal 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>
|
@ -5,6 +5,8 @@ import android.os.Build
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.foundation.Canvas
|
import androidx.compose.foundation.Canvas
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
@ -425,7 +427,8 @@ fun LazyItemScope.ActionItem(idx: Int, action: Action, onSelect: (Action) -> Uni
|
|||||||
if (!dragging.value) {
|
if (!dragging.value) {
|
||||||
it.animateItemPlacement()
|
it.animateItemPlacement()
|
||||||
} else {
|
} else {
|
||||||
it.zIndex(10.0f)
|
it
|
||||||
|
.zIndex(10.0f)
|
||||||
.graphicsLayer {
|
.graphicsLayer {
|
||||||
clip = false
|
clip = false
|
||||||
translationX = offsetX.floatValue
|
translationX = offsetX.floatValue
|
||||||
@ -602,6 +605,12 @@ fun ActionBar(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(inlineSuggestions) {
|
||||||
|
if(inlineSuggestions.isNotEmpty()) {
|
||||||
|
isActionsOpen.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Surface(modifier = Modifier
|
Surface(modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(40.dp), color = MaterialTheme.colorScheme.background)
|
.height(40.dp), color = MaterialTheme.colorScheme.background)
|
||||||
@ -624,9 +633,13 @@ fun ActionBar(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!isActionsOpen.value) {
|
if(!isActionsOpen.value) {
|
||||||
if (inlineSuggestions.isNotEmpty() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
AnimatedVisibility(inlineSuggestions.isNotEmpty(), enter = fadeIn(), exit = fadeOut()) {
|
||||||
InlineSuggestions(inlineSuggestions)
|
InlineSuggestions(inlineSuggestions)
|
||||||
} else if (words != null) {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (words != null && inlineSuggestions.isEmpty()) {
|
||||||
SuggestionItems(
|
SuggestionItems(
|
||||||
words,
|
words,
|
||||||
onClick = {
|
onClick = {
|
||||||
@ -700,7 +713,6 @@ fun CollapsibleSuggestionsBar(
|
|||||||
onCollapse: () -> Unit,
|
onCollapse: () -> Unit,
|
||||||
words: SuggestedWords?,
|
words: SuggestedWords?,
|
||||||
suggestionStripListener: SuggestionStripView.Listener,
|
suggestionStripListener: SuggestionStripView.Listener,
|
||||||
inlineSuggestions: List<MutableState<View?>>,
|
|
||||||
) {
|
) {
|
||||||
Surface(modifier = Modifier
|
Surface(modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -726,9 +738,7 @@ fun CollapsibleSuggestionsBar(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(inlineSuggestions.isNotEmpty() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if(words != null) {
|
||||||
InlineSuggestions(inlineSuggestions)
|
|
||||||
} else if(words != null) {
|
|
||||||
SuggestionItems(words, onClick = {
|
SuggestionItems(words, onClick = {
|
||||||
suggestionStripListener.pickSuggestionManually(
|
suggestionStripListener.pickSuggestionManually(
|
||||||
words.getInfo(it)
|
words.getInfo(it)
|
||||||
@ -879,8 +889,7 @@ fun PreviewCollapsibleBar(colorScheme: ColorScheme = DarkColorScheme) {
|
|||||||
onCollapse = { },
|
onCollapse = { },
|
||||||
onClose = { },
|
onClose = { },
|
||||||
words = exampleSuggestedWords,
|
words = exampleSuggestedWords,
|
||||||
suggestionStripListener = ExampleListener(),
|
suggestionStripListener = ExampleListener()
|
||||||
inlineSuggestions = listOf()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,8 +2,10 @@ package org.futo.inputmethod.latin.uix
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.drawable.Icon
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.inputmethod.InlineSuggestion
|
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.TextViewStyle
|
||||||
import androidx.autofill.inline.common.ViewStyle
|
import androidx.autofill.inline.common.ViewStyle
|
||||||
import androidx.autofill.inline.v1.InlineSuggestionUi
|
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.RowScope
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.material3.ColorScheme
|
import androidx.compose.material3.ColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.key
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.viewinterop.AndroidView
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
|
import org.futo.inputmethod.latin.R
|
||||||
import kotlin.math.roundToInt
|
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")
|
@SuppressLint("RestrictedApi")
|
||||||
@RequiresApi(Build.VERSION_CODES.R)
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
fun createInlineSuggestionsRequest(
|
fun createInlineSuggestionsRequest(
|
||||||
@ -39,17 +56,24 @@ fun createInlineSuggestionsRequest(
|
|||||||
context.fromDp(v).roundToInt()
|
context.fromDp(v).roundToInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val drawable = R.drawable.inline_suggestion_chip
|
||||||
|
val bgColor = activeColorScheme.secondaryContainer.toArgb()
|
||||||
|
|
||||||
val stylesBuilder = UiVersions.newStylesBuilder()
|
val stylesBuilder = UiVersions.newStylesBuilder()
|
||||||
val suggestionStyle = InlineSuggestionUi.newStyleBuilder()
|
val suggestionStyle = InlineSuggestionUi.newStyleBuilder()
|
||||||
.setSingleIconChipStyle(
|
.setSingleIconChipStyle(
|
||||||
ViewStyle.Builder()
|
ViewStyle.Builder()
|
||||||
.setBackgroundColor(activeColorScheme.secondaryContainer.toArgb())
|
.setBackground(
|
||||||
|
Icon.createWithResource(context, drawable).setTint(bgColor)
|
||||||
|
)
|
||||||
.setPadding(0, 0, 0, 0)
|
.setPadding(0, 0, 0, 0)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
.setChipStyle(
|
.setChipStyle(
|
||||||
ViewStyle.Builder()
|
ViewStyle.Builder()
|
||||||
.setBackgroundColor(activeColorScheme.secondaryContainer.toArgb())
|
.setBackground(
|
||||||
|
Icon.createWithResource(context, drawable).setTint(bgColor)
|
||||||
|
)
|
||||||
.setPadding(
|
.setPadding(
|
||||||
fromDp(8.0f),
|
fromDp(8.0f),
|
||||||
fromDp(0.0f),
|
fromDp(0.0f),
|
||||||
@ -93,13 +117,23 @@ fun createInlineSuggestionsRequest(
|
|||||||
|
|
||||||
val stylesBundle = stylesBuilder.build()
|
val stylesBundle = stylesBuilder.build()
|
||||||
|
|
||||||
|
val displayMetrics = context.resources.displayMetrics
|
||||||
|
|
||||||
|
val maxWidthPx = displayMetrics.widthPixels * 2 / 3
|
||||||
|
|
||||||
val spec = InlinePresentationSpec.Builder(
|
val spec = InlinePresentationSpec.Builder(
|
||||||
Size(0, 0),
|
Size(
|
||||||
Size(Int.MAX_VALUE, Int.MAX_VALUE)
|
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()
|
).setStyle(stylesBundle).build()
|
||||||
|
|
||||||
return InlineSuggestionsRequest.Builder(listOf(spec)).let { request ->
|
return InlineSuggestionsRequest.Builder(List(maxSuggestions) { spec }).let { request ->
|
||||||
request.setMaxSuggestionCount(InlineSuggestionsRequest.SUGGESTION_COUNT_UNLIMITED)
|
request.setMaxSuggestionCount(maxSuggestions)
|
||||||
request.build()
|
request.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,24 +160,26 @@ fun Context.inflateInlineSuggestion(inlineSuggestion: InlineSuggestion): Mutable
|
|||||||
@RequiresApi(Build.VERSION_CODES.R)
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
@Composable
|
@Composable
|
||||||
fun InlineSuggestionView(inlineSuggestion: MutableState<View?>) {
|
fun InlineSuggestionView(inlineSuggestion: MutableState<View?>) {
|
||||||
|
key(inlineSuggestion.value) {
|
||||||
if (inlineSuggestion.value != null) {
|
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(
|
AndroidView(
|
||||||
factory = { inlineSuggestion.value!! },
|
factory = { inlineSuggestion.value!! },
|
||||||
modifier = Modifier.padding(4.dp, 0.dp)
|
modifier = Modifier.padding(4.dp, 0.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.R)
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
@Composable
|
@Composable
|
||||||
fun RowScope.InlineSuggestions(suggestions: List<MutableState<View?>>) {
|
fun RowScope.InlineSuggestions(suggestions: List<MutableState<View?>>) {
|
||||||
LazyRow(modifier = Modifier
|
val scrollState = rememberScrollState()
|
||||||
|
Row(modifier = Modifier
|
||||||
.weight(1.0f)
|
.weight(1.0f)
|
||||||
.padding(0.dp, 4.dp)) {
|
.padding(0.dp, 4.dp)
|
||||||
items(suggestions.size) {
|
.horizontalScroll(scrollState)
|
||||||
InlineSuggestionView(suggestions[it])
|
.clipScrollableContainer(Orientation.Horizontal)
|
||||||
}
|
.clipToBounds()) {
|
||||||
|
suggestions.forEach { InlineSuggestionView(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -328,8 +328,7 @@ class UixManager(private val latinIME: LatinIME) {
|
|||||||
onCollapse = { toggleExpandAction() },
|
onCollapse = { toggleExpandAction() },
|
||||||
onClose = { returnBackToMainKeyboardViewFromAction() },
|
onClose = { returnBackToMainKeyboardViewFromAction() },
|
||||||
words = suggestedWordsOrNull,
|
words = suggestedWordsOrNull,
|
||||||
suggestionStripListener = latinIME.latinIMELegacy as SuggestionStripView.Listener,
|
suggestionStripListener = latinIME.latinIMELegacy as SuggestionStripView.Listener
|
||||||
inlineSuggestions = inlineSuggestions
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user