mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
Fix context menu in chat
Signed-off-by: denis0001-dev <denis0001.dev@ya.ru>
This commit is contained in:
@@ -10,11 +10,8 @@ import androidx.compose.animation.expandVertically
|
|||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.animation.shrinkVertically
|
import androidx.compose.animation.shrinkVertically
|
||||||
import androidx.compose.foundation.LocalIndication
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
@@ -177,10 +174,11 @@ fun MessageItem(
|
|||||||
val isDeletedSender = messageSenderIsDeleted(message, currentUserId)
|
val isDeletedSender = messageSenderIsDeleted(message, currentUserId)
|
||||||
val replyRef = message.reply_to
|
val replyRef = message.reply_to
|
||||||
|
|
||||||
var isPressed by remember { mutableStateOf(false) }
|
var isPressed by remember(message.id) { mutableStateOf(false) }
|
||||||
var avatarPressed by remember(message.id) { mutableStateOf(false) }
|
var avatarPressed by remember(message.id) { mutableStateOf(false) }
|
||||||
var replyPressed by remember(message.id) { mutableStateOf(false) }
|
var replyPressed by remember(message.id) { mutableStateOf(false) }
|
||||||
var rowLayoutCoords by remember(message.id) { mutableStateOf<LayoutCoordinates?>(null) }
|
var rowLayoutCoords by remember(message.id) { mutableStateOf<LayoutCoordinates?>(null) }
|
||||||
|
var bubbleContentCoords by remember(message.id) { mutableStateOf<LayoutCoordinates?>(null) }
|
||||||
val scaleTarget = if (isPressed && !isContextMenuForThisMessage && !isContextMenuOpen) 0.96f else 1f
|
val scaleTarget = if (isPressed && !isContextMenuForThisMessage && !isContextMenuOpen) 0.96f else 1f
|
||||||
val avatarScaleTarget = if (avatarPressed && !isContextMenuOpen) 0.96f else 1f
|
val avatarScaleTarget = if (avatarPressed && !isContextMenuOpen) 0.96f else 1f
|
||||||
val replyScaleTarget = if (replyPressed && !isContextMenuOpen) 0.96f else 1f
|
val replyScaleTarget = if (replyPressed && !isContextMenuOpen) 0.96f else 1f
|
||||||
@@ -376,7 +374,7 @@ fun MessageItem(
|
|||||||
|
|
||||||
val rowLongPress =
|
val rowLongPress =
|
||||||
if (isContextMenuOpen) Modifier
|
if (isContextMenuOpen) Modifier
|
||||||
else Modifier.pointerInput(isContextMenuOpen, message.id) {
|
else Modifier.pointerInput(message.id, onLongPress) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onPress = {
|
onPress = {
|
||||||
isPressed = true
|
isPressed = true
|
||||||
@@ -490,21 +488,30 @@ fun MessageItem(
|
|||||||
message.files?.firstOrNull()?.let { isImageFilename(it.name) } == true
|
message.files?.firstOrNull()?.let { isImageFilename(it.name) } == true
|
||||||
)
|
)
|
||||||
|
|
||||||
val bubbleTap =
|
val bubbleBodyGestures =
|
||||||
if (isContextMenuOpen || onBubbleTap == null) Modifier
|
if (isContextMenuOpen) Modifier
|
||||||
else Modifier.pointerInput(message.id, onBubbleTap) {
|
else Modifier
|
||||||
detectTapGestures(
|
.onGloballyPositioned { bubbleContentCoords = it }
|
||||||
onPress = {
|
.pointerInput(message.id, onBubbleTap, onLongPress) {
|
||||||
isPressed = true
|
detectTapGestures(
|
||||||
try {
|
onPress = {
|
||||||
awaitRelease()
|
isPressed = true
|
||||||
} finally {
|
try {
|
||||||
isPressed = false
|
awaitRelease()
|
||||||
}
|
} finally {
|
||||||
},
|
isPressed = false
|
||||||
onTap = { onBubbleTap.invoke() },
|
}
|
||||||
)
|
},
|
||||||
}
|
onTap = { onBubbleTap?.invoke() },
|
||||||
|
onLongPress = { localOffset ->
|
||||||
|
val coords = bubbleContentCoords
|
||||||
|
if (coords != null && coords.isAttached) {
|
||||||
|
onTapPosition(coords.localToRoot(localOffset))
|
||||||
|
}
|
||||||
|
onLongPress()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Box {
|
Box {
|
||||||
Column(
|
Column(
|
||||||
@@ -550,16 +557,38 @@ fun MessageItem(
|
|||||||
val usernameInset =
|
val usernameInset =
|
||||||
Modifier.padding(horizontal = 4.dp, vertical = 2.dp)
|
Modifier.padding(horizontal = 4.dp, vertical = 2.dp)
|
||||||
if (onUsernameClick != null) {
|
if (onUsernameClick != null) {
|
||||||
val usernameInteraction =
|
|
||||||
remember(message.id) { MutableInteractionSource() }
|
|
||||||
Box(
|
Box(
|
||||||
modifier = usernameOutset
|
modifier = usernameOutset
|
||||||
.clip(usernameShape)
|
.clip(usernameShape)
|
||||||
.clickable(
|
.pointerInput(message.id, onUsernameClick) {
|
||||||
interactionSource = usernameInteraction,
|
detectTapGestures(
|
||||||
indication = LocalIndication.current,
|
onPress = {
|
||||||
onClick = onUsernameClick
|
isPressed = true
|
||||||
)
|
try {
|
||||||
|
awaitRelease()
|
||||||
|
} finally {
|
||||||
|
isPressed = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onTap = { onUsernameClick.invoke() },
|
||||||
|
onLongPress = {
|
||||||
|
val coords = bubbleContentCoords
|
||||||
|
if (
|
||||||
|
coords != null &&
|
||||||
|
coords.isAttached
|
||||||
|
) {
|
||||||
|
val center = Offset(
|
||||||
|
coords.size.width / 2f,
|
||||||
|
coords.size.height / 2f,
|
||||||
|
)
|
||||||
|
onTapPosition(
|
||||||
|
coords.localToRoot(center),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onLongPress()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
@@ -579,7 +608,38 @@ fun MessageItem(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Box(modifier = usernameOutset) {
|
Box(
|
||||||
|
modifier = usernameOutset
|
||||||
|
.pointerInput(message.id, onBubbleTap) {
|
||||||
|
detectTapGestures(
|
||||||
|
onPress = {
|
||||||
|
isPressed = true
|
||||||
|
try {
|
||||||
|
awaitRelease()
|
||||||
|
} finally {
|
||||||
|
isPressed = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onTap = { onBubbleTap?.invoke() },
|
||||||
|
onLongPress = {
|
||||||
|
val coords = bubbleContentCoords
|
||||||
|
if (
|
||||||
|
coords != null &&
|
||||||
|
coords.isAttached
|
||||||
|
) {
|
||||||
|
val center = Offset(
|
||||||
|
coords.size.width / 2f,
|
||||||
|
coords.size.height / 2f,
|
||||||
|
)
|
||||||
|
onTapPosition(
|
||||||
|
coords.localToRoot(center),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onLongPress()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
@@ -600,11 +660,7 @@ fun MessageItem(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Box(
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.then(bubbleTap)
|
|
||||||
) {
|
|
||||||
Column {
|
Column {
|
||||||
replyRef?.let { replyToMsg ->
|
replyRef?.let { replyToMsg ->
|
||||||
MessageReplyQuote(
|
MessageReplyQuote(
|
||||||
@@ -620,6 +676,12 @@ fun MessageItem(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.then(bubbleBodyGestures),
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
if (isCorrupted) {
|
if (isCorrupted) {
|
||||||
Text(
|
Text(
|
||||||
text = corruptedBody,
|
text = corruptedBody,
|
||||||
@@ -850,6 +912,8 @@ fun MessageItem(
|
|||||||
modifier = Modifier.padding(horizontal = 14.dp)
|
modifier = Modifier.padding(horizontal = 14.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -981,7 +1045,7 @@ private fun MessageReplyQuote(
|
|||||||
|
|
||||||
val replyPressModifier =
|
val replyPressModifier =
|
||||||
if (replyTapEnabled && !isContextMenuOpen) {
|
if (replyTapEnabled && !isContextMenuOpen) {
|
||||||
Modifier.pointerInput(replyTo.id, isContextMenuOpen) {
|
Modifier.pointerInput(replyTo.id) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onPress = {
|
onPress = {
|
||||||
onReplyPressedChange(true)
|
onReplyPressedChange(true)
|
||||||
|
|||||||
Reference in New Issue
Block a user