Separate some compose UI components to make things more understandable

This commit is contained in:
Aleksandras Kostarevas 2024-09-27 20:20:18 +03:00
parent 2e2bba2ac2
commit 112b7a291a

View File

@ -4,6 +4,7 @@ import android.app.Activity
import android.content.ClipDescription import android.content.ClipDescription
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Rect
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.VibrationEffect import android.os.VibrationEffect
@ -57,12 +58,14 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.runtime.staticCompositionLocalOf
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.clipToBounds
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
@ -107,6 +110,7 @@ import org.futo.inputmethod.updates.deferManualUpdate
import org.futo.inputmethod.updates.isManualUpdateTimeExpired import org.futo.inputmethod.updates.isManualUpdateTimeExpired
import org.futo.inputmethod.updates.openManualUpdateCheck import org.futo.inputmethod.updates.openManualUpdateCheck
import org.futo.inputmethod.updates.retrieveSavedLastUpdateCheckResult import org.futo.inputmethod.updates.retrieveSavedLastUpdateCheckResult
import org.futo.inputmethod.v2keyboard.ComputedKeyboardSize
import org.futo.inputmethod.v2keyboard.FloatingKeyboardSize import org.futo.inputmethod.v2keyboard.FloatingKeyboardSize
import org.futo.inputmethod.v2keyboard.KeyboardSizingCalculator import org.futo.inputmethod.v2keyboard.KeyboardSizingCalculator
import org.futo.inputmethod.v2keyboard.OneHandedDirection import org.futo.inputmethod.v2keyboard.OneHandedDirection
@ -659,45 +663,90 @@ class UixManager(private val latinIME: LatinIME) {
} }
@Composable @Composable
fun SizePositionerSurface(content: @Composable BoxScope.(actionBarGap: Dp) -> Unit) { private fun OffsetPositioner(offset: Offset, content: @Composable () -> Unit) {
val size = latinIME.size.value Column(modifier = Modifier.fillMaxHeight().absoluteOffset { IntOffset(offset.x.toInt(), 0) }) {
when(size) {
is FloatingKeyboardSize -> {
val offset = remember(size) { mutableStateOf(Offset(size.bottomOrigin.first.toFloat(), size.bottomOrigin.second.toFloat())) }
val configuration = LocalConfiguration.current
with(LocalDensity.current) {
Column(modifier = Modifier.fillMaxHeight().absoluteOffset { IntOffset(offset.value.x.toInt(), 0) }) {
Spacer(Modifier.weight(1.0f)) Spacer(Modifier.weight(1.0f))
Column(Modifier content()
.background(latinIME.keyboardColor, RoundedCornerShape(8.dp)) Spacer(Modifier.height(with(LocalDensity.current) { offset.y.toDp() }))
.requiredWidth(size.width.toDp())
.onSizeChanged {
measuredTouchableHeight = it.height
} }
}
@Composable
private fun KeyboardSurface(
requiredWidthPx: Int,
backgroundColor: Color,
modifier: Modifier = Modifier,
shape: Shape = RectangleShape,
padding: Rect = Rect(),
content: @Composable BoxScope.() -> Unit
) = with(LocalDensity.current) {
Box(modifier
.onSizeChanged { measuredTouchableHeight = it.height}
.background(backgroundColor, shape)
.requiredWidth(requiredWidthPx.toDp())
.absolutePadding( .absolutePadding(
left = size.decorationPadding.left.toDp(), left = padding.left.toDp(),
top = 0.dp, top = padding.top.toDp(),
right = size.decorationPadding.right.toDp(), right = padding.right.toDp(),
bottom = 0.dp, bottom = padding.bottom.toDp(),
) )
.clipToBounds()
) { ) {
CompositionLocalProvider(LocalContentColor provides contentColorFor(backgroundColor)) {
content()
}
}
}
@Composable
private fun FloatingKeyboardContents(
pointerInputKey: Any?,
onDragged: (Offset) -> Unit,
onDragEnd: () -> Unit,
content: @Composable BoxScope.(actionBarGap: Dp) -> Unit
) {
// Content
Box(Modifier.fillMaxWidth()) { Box(Modifier.fillMaxWidth()) {
CompositionLocalProvider(
LocalContentColor provides contentColorFor(
latinIME.keyboardColor
)
) {
content(4.dp) content(4.dp)
} }
}
// Bottom drag bar
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
Box(modifier = Modifier Box(modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(20.dp) .height(20.dp)
.pointerInput(size) { .pointerInput(pointerInputKey) {
detectDragGestures(onDrag = { change, dragAmount -> detectDragGestures(
onDrag = { _, dragAmount -> onDragged(dragAmount)},
onDragEnd = { onDragEnd() })
}) {
Box(
modifier = Modifier.fillMaxWidth(0.6f).height(4.dp)
.align(Alignment.TopCenter).background(
MaterialTheme.colorScheme.onBackground.copy(alpha = 0.6f),
RoundedCornerShape(100)
)
)
}
}
@Composable
private fun FloatingKeyboardWindow(
size: FloatingKeyboardSize,
content: @Composable BoxScope.(actionBarGap: Dp) -> Unit
) = with(LocalDensity.current) {
val offset = remember(size) { mutableStateOf(Offset(size.bottomOrigin.first.toFloat(), size.bottomOrigin.second.toFloat())) }
OffsetPositioner(offset.value) {
KeyboardSurface(
requiredWidthPx = size.width,
backgroundColor = latinIME.keyboardColor,
shape = RoundedCornerShape(16.dp),
padding = size.decorationPadding
) {
Column {
FloatingKeyboardContents(
pointerInputKey = size,
onDragged = { dragAmount ->
var newOffset = offset.value.copy( var newOffset = offset.value.copy(
x = offset.value.x + dragAmount.x, x = offset.value.x + dragAmount.x,
y = offset.value.y - dragAmount.y y = offset.value.y - dragAmount.y
@ -709,12 +758,17 @@ class UixManager(private val latinIME: LatinIME) {
newOffset.y.coerceAtLeast(0.0f) newOffset.y.coerceAtLeast(0.0f)
) )
newOffset = newOffset.copy( newOffset = newOffset.copy(
newOffset.x.coerceAtMost(latinIME.getViewWidth().toFloat() - size.width), newOffset.x.coerceAtMost(
newOffset.y.coerceAtMost(latinIME.getViewHeight().toFloat() - measuredTouchableHeight) latinIME.getViewWidth().toFloat() - size.width
),
newOffset.y.coerceAtMost(
latinIME.getViewHeight().toFloat() - measuredTouchableHeight
)
) )
offset.value = newOffset offset.value = newOffset
}, onDragEnd = { },
onDragEnd = {
latinIME.sizingCalculator.editSavedSettings { settings -> latinIME.sizingCalculator.editSavedSettings { settings ->
settings.copy( settings.copy(
floatingBottomOriginDp = Pair( floatingBottomOriginDp = Pair(
@ -723,35 +777,27 @@ class UixManager(private val latinIME: LatinIME) {
) )
) )
} }
}) },
}) { content = content
Box(modifier = Modifier.fillMaxWidth(0.6f).height(4.dp).align(Alignment.TopCenter).background( )
MaterialTheme.colorScheme.onBackground.copy(alpha = 0.6f), RoundedCornerShape(100)
))
}
}
Spacer(Modifier.height(offset.value.y.toDp()))
} }
} }
} }
is OneHandedKeyboardSize, }
is RegularKeyboardSize,
is SplitKeyboardSize -> { @Composable
Column { private fun NonFloatingKeyboardWindow(
Spacer(modifier = Modifier.weight(1.0f)) size: ComputedKeyboardSize,
Surface(modifier = Modifier.onSizeChanged { content: @Composable BoxScope.(actionBarGap: Dp) -> Unit
measuredTouchableHeight = it.height ) = with(LocalDensity.current) {
}, color = latinIME.keyboardColor) { OffsetPositioner(Offset(0.0f, 0.0f)) {
with(LocalDensity.current) { KeyboardSurface(
val actionBarGap = (size.getPadding().top / 2).toDp() requiredWidthPx = size.getWidth(),
Box(Modifier.absolutePadding( backgroundColor = latinIME.keyboardColor,
left = size.getPadding().left.toDp(), padding = size.getPadding()
top = actionBarGap, ) {
right = size.getPadding().right.toDp(), val actionBarGap = 4.dp
bottom = size.getPadding().bottom.toDp(),
).width(
(size.getWidth() - size.getPadding().left - size.getPadding().right).toDp()
)) {
when(size) { when(size) {
is OneHandedKeyboardSize -> { is OneHandedKeyboardSize -> {
Box(modifier = Modifier.width(size.layoutWidth.toDp()).align( Box(modifier = Modifier.width(size.layoutWidth.toDp()).align(
@ -763,38 +809,54 @@ class UixManager(private val latinIME: LatinIME) {
content(actionBarGap) content(actionBarGap)
} }
} }
is RegularKeyboardSize -> { else -> {
content(actionBarGap) content(actionBarGap)
} }
is SplitKeyboardSize -> {
content(actionBarGap)
} }
else -> throw IllegalStateException() }
} }
} }
} @Composable
} fun KeyboardWindowSelector(content: @Composable BoxScope.(actionBarGap: Dp) -> Unit) {
} val size = latinIME.size.value
} when(size) {
is FloatingKeyboardSize -> FloatingKeyboardWindow(size, content)
is OneHandedKeyboardSize,
is RegularKeyboardSize,
is SplitKeyboardSize -> NonFloatingKeyboardWindow(size, content)
null -> return null -> return
} }
} }
fun setContent() { @Composable
composeView?.setContent { private fun ProvidersAndWrapper(content: @Composable () -> Unit) {
UixThemeWrapper(latinIME.colorScheme) { UixThemeWrapper(latinIME.colorScheme) {
DataStoreCacheProvider { DataStoreCacheProvider {
CompositionLocalProvider(LocalManager provides keyboardManagerForAction) { CompositionLocalProvider(LocalManager provides keyboardManagerForAction) {
CompositionLocalProvider(LocalThemeProvider provides latinIME.getDrawableProvider()) { CompositionLocalProvider(LocalThemeProvider provides latinIME.getDrawableProvider()) {
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) { CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
CompositionLocalProvider(LocalFoldingState provides foldingOptions.value) { CompositionLocalProvider(LocalFoldingState provides foldingOptions.value) {
content()
}
}
}
}
}
}
}
fun setContent() {
composeView?.setContent {
ProvidersAndWrapper {
InputDarkener(isInputOverridden.value || isShowingActionEditor.value) { InputDarkener(isInputOverridden.value || isShowingActionEditor.value) {
closeActionWindow() closeActionWindow()
isShowingActionEditor.value = false isShowingActionEditor.value = false
} }
SizePositionerSurface { gap -> KeyboardWindowSelector { gap ->
Column { Column {
when { when {
currWindowActionWindow != null -> ActionViewWithHeader( currWindowActionWindow != null -> ActionViewWithHeader(
@ -816,11 +878,6 @@ class UixManager(private val latinIME: LatinIME) {
} }
} }
} }
}
}
}
}
}
suspend fun showUpdateNoticeIfNeeded() { suspend fun showUpdateNoticeIfNeeded() {
if(!BuildConfig.UPDATE_CHECKING) return if(!BuildConfig.UPDATE_CHECKING) return