Improving the ui for reaction row settings

This commit is contained in:
Vitor Pamplona
2026-03-04 17:37:52 -05:00
parent f4ec5735d3
commit cb6391085a
@@ -21,8 +21,10 @@
package com.vitorpamplona.amethyst.ui.screen.loggedIn.settings package com.vitorpamplona.amethyst.ui.screen.loggedIn.settings
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.gestures.detectDragGesturesAfterLongPress import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
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.Spacer import androidx.compose.foundation.layout.Spacer
@@ -31,10 +33,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.DragHandle import androidx.compose.material.icons.filled.DragIndicator
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@@ -56,17 +57,32 @@ import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex import androidx.compose.ui.zIndex
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.ReactionRowAction import com.vitorpamplona.amethyst.model.ReactionRowAction
import com.vitorpamplona.amethyst.model.ReactionRowItem import com.vitorpamplona.amethyst.model.ReactionRowItem
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.Size20dp import com.vitorpamplona.amethyst.ui.theme.Size20dp
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonRow
@Composable
@Preview(device = "spec:width=2100px,height=2340px,dpi=440")
fun ReactionsSettingsScreenPreview() {
ThemeComparisonRow {
ReactionsSettingsScreen(
mockAccountViewModel(),
EmptyNav(),
)
}
}
@Composable @Composable
fun ReactionsSettingsScreen( fun ReactionsSettingsScreen(
@@ -97,13 +113,14 @@ fun ReactionsSettingsContent(accountViewModel: AccountViewModel) {
var draggedItemIndex by remember { mutableIntStateOf(-1) } var draggedItemIndex by remember { mutableIntStateOf(-1) }
var dragOffset by remember { mutableFloatStateOf(0f) } var dragOffset by remember { mutableFloatStateOf(0f) }
val itemHeights = remember { mutableStateMapOf<Int, Float>() } val itemHeights = remember { mutableStateMapOf<Int, Float>() }
val isDragging = draggedItemIndex >= 0
val scrollState = remember { ScrollState(0) }
Column( Column(
modifier = modifier =
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.padding(horizontal = Size20dp) .verticalScroll(scrollState, enabled = !isDragging),
.verticalScroll(rememberScrollState()),
) { ) {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
@@ -111,7 +128,7 @@ fun ReactionsSettingsContent(accountViewModel: AccountViewModel) {
text = stringRes(R.string.reactions_settings_description), text = stringRes(R.string.reactions_settings_description),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = Color.Gray, color = Color.Gray,
modifier = Modifier.padding(bottom = 16.dp), modifier = Modifier.padding(bottom = 16.dp, start = Size20dp, end = Size20dp),
) )
items.forEachIndexed { index, item -> items.forEachIndexed { index, item ->
@@ -206,7 +223,7 @@ fun ReactionsSettingsContent(accountViewModel: AccountViewModel) {
.zIndex(if (isDragging) 1f else 0f), .zIndex(if (isDragging) 1f else 0f),
) )
if (index < items.lastIndex) { if (index < items.lastIndex) {
HorizontalDivider() HorizontalDivider(modifier = Modifier.padding(horizontal = Size20dp))
} }
} }
@@ -238,16 +255,25 @@ private fun ReactionRowItemCard(
.fillMaxWidth() .fillMaxWidth()
.onGloballyPositioned { coordinates -> .onGloballyPositioned { coordinates ->
onMeasured(coordinates.size.height.toFloat()) onMeasured(coordinates.size.height.toFloat())
} }.graphicsLayer {
.graphicsLayer {
translationY = dragOffsetY translationY = dragOffsetY
shadowElevation = elevation shadowElevation = elevation
if (isDragging) { if (isDragging) {
scaleX = 1.02f scaleX = 1.02f
scaleY = 1.02f scaleY = 1.02f
} }
} }.padding(vertical = 8.dp, horizontal = Size20dp)
.padding(vertical = 8.dp), .pointerInput(Unit) {
detectDragGestures(
onDragStart = { onDragStart() },
onDrag = { change, dragAmount ->
change.consume()
onDrag(dragAmount.y)
},
onDragEnd = { onDragEnd() },
onDragCancel = { onDragCancel() },
)
},
) { ) {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -270,26 +296,18 @@ private fun ReactionRowItemCard(
) )
} }
Box(
modifier = Modifier.size(32.dp),
contentAlignment = Alignment.CenterEnd,
) {
Icon( Icon(
Icons.Default.DragHandle, Icons.Default.DragIndicator,
contentDescription = stringRes(R.string.reactions_settings_reorder), contentDescription = stringRes(R.string.reactions_settings_reorder),
modifier = modifier = Modifier.size(28.dp),
Modifier
.size(32.dp)
.pointerInput(Unit) {
detectDragGesturesAfterLongPress(
onDragStart = { onDragStart() },
onDrag = { change, dragAmount ->
change.consume()
onDrag(dragAmount.y)
},
onDragEnd = { onDragEnd() },
onDragCancel = { onDragCancel() },
)
},
tint = MaterialTheme.colorScheme.onSurfaceVariant, tint = MaterialTheme.colorScheme.onSurfaceVariant,
) )
} }
}
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))