update reaction ui

This commit is contained in:
2026-09-07 16:57:21 +07:00
parent a8c73f804e
commit c4d3870a02
@@ -478,14 +478,11 @@ fun ChatScreen(
val (model, bounds) = selectedMessage ?: return@AnimatedVisibility val (model, bounds) = selectedMessage ?: return@AnimatedVisibility
val density = LocalDensity.current val density = LocalDensity.current
val windowInfo = LocalWindowInfo.current
val windowHeight = windowInfo.containerSize.height
val scrollState = rememberScrollState() val scrollState = rememberScrollState()
var menuHeight by remember { mutableFloatStateOf(0f) } var menuHeight by remember { mutableFloatStateOf(0f) }
val spacing = with(density) { 12.dp.toPx() } var toolbarHeight by remember { mutableFloatStateOf(0f) }
val showAbove = val spacing = with(density) { 6.dp.toPx() }
(windowHeight - bounds.bottom) < (menuHeight + spacing) && bounds.top > (menuHeight + spacing)
Box( Box(
modifier = Modifier modifier = Modifier
@@ -494,11 +491,30 @@ fun ChatScreen(
.clickable { selectedMessage = null } .clickable { selectedMessage = null }
.verticalScroll(scrollState), .verticalScroll(scrollState),
) { ) {
val totalExtraHeight = if (menuHeight > 0) menuHeight + spacing else 300f val totalExtraHeight = (if (menuHeight > 0) menuHeight + spacing else 300f) +
(if (toolbarHeight > 0) toolbarHeight + spacing else 100f)
val contentBottom = with(density) { (bounds.bottom + totalExtraHeight).toDp() } val contentBottom = with(density) { (bounds.bottom + totalExtraHeight).toDp() }
Spacer(modifier = Modifier.height(contentBottom + 200.dp)) Spacer(modifier = Modifier.height(contentBottom + 200.dp))
// Reaction Toolbar (Above)
Box(
modifier = Modifier
.offset { IntOffset(0, (bounds.top - toolbarHeight - spacing).toInt().coerceAtLeast(0)) }
.onGloballyPositioned { toolbarHeight = it.size.height.toFloat() }
.fillMaxWidth()
.padding(horizontal = 16.dp),
contentAlignment = if (model.isMine) Alignment.CenterEnd else Alignment.CenterStart
) {
ReactionToolbar(
onReaction = { reaction ->
viewModel.sendReaction(model.id, reaction)
selectedMessage = null
}
)
}
// Message Preview
ChatMessage( ChatMessage(
model = model, model = model,
modifier = Modifier modifier = Modifier
@@ -506,15 +522,10 @@ fun ChatScreen(
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp)
) )
val menuOffset = if (showAbove) { // Action Menu (Below)
bounds.top - menuHeight - spacing
} else {
bounds.bottom + spacing
}
Box( Box(
modifier = Modifier modifier = Modifier
.offset { IntOffset(0, menuOffset.toInt().coerceAtLeast(0)) } .offset { IntOffset(0, (bounds.bottom + spacing).toInt()) }
.onGloballyPositioned { menuHeight = it.size.height.toFloat() } .onGloballyPositioned { menuHeight = it.size.height.toFloat() }
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp), .padding(horizontal = 16.dp),
@@ -538,10 +549,6 @@ fun ChatScreen(
else -> {} else -> {}
} }
selectedMessage = null selectedMessage = null
},
onReaction = { reaction ->
viewModel.sendReaction(model.id, reaction)
selectedMessage = null
} }
) )
} }
@@ -642,41 +649,53 @@ private fun ReplyPreview(
} }
} }
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
private fun ContextMenu( private fun ReactionToolbar(
onAction: (String) -> Unit,
onReaction: (String) -> Unit onReaction: (String) -> Unit
) { ) {
val menuItems = listOf( val reactionEmojis = listOf("👍", "❤️", "😂", "😮", "😢", "😡", "🎉")
"Copy" to Res.drawable.ic_copy,
"Reply" to Res.drawable.ic_reply
)
val reactionEmojis = listOf("👍", "❤️", "👀", "🔥", "🚀", "🎉") Surface(
color = MaterialTheme.colorScheme.surfaceContainerHigh,
DropdownMenuGroup( shape = RoundedCornerShape(24.dp),
shapes = MenuDefaults.groupShape(1, 1), shadowElevation = 1.dp
containerColor = MenuDefaults.groupVibrantContainerColor,
modifier = Modifier.width(240.dp)
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .padding(horizontal = 12.dp, vertical = 8.dp),
.padding(vertical = 8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.SpaceEvenly verticalAlignment = Alignment.CenterVertically
) { ) {
reactionEmojis.forEach { emoji -> reactionEmojis.forEach { emoji ->
Text( Text(
text = emoji, text = emoji,
modifier = Modifier modifier = Modifier
.clickable { onReaction(emoji) } .clickable { onReaction(emoji) }
.padding(horizontal = 4.dp), .padding(4.dp),
fontSize = 24.sp fontSize = 24.sp
) )
} }
} }
}
}
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
private fun ContextMenu(
onAction: (String) -> Unit
) {
val menuItems = listOf(
"Copy" to Res.drawable.ic_copy,
"Reply" to Res.drawable.ic_reply
)
DropdownMenuGroup(
shapes = MenuDefaults.groupShape(1, 1),
containerColor = MenuDefaults.groupVibrantContainerColor,
tonalElevation = 1.dp,
shadowElevation = 1.dp,
modifier = Modifier.width(220.dp)
) {
val itemCount = menuItems.size val itemCount = menuItems.size
menuItems.forEachIndexed { index, (label, icon) -> menuItems.forEachIndexed { index, (label, icon) ->