update reaction ui
This commit is contained in:
@@ -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) ->
|
||||||
|
|||||||
Reference in New Issue
Block a user