mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-27 22:34:51 +00:00
android, desktop: fix chat item long-press menu and ripple shape (#6997)
* android, desktop: fix chat item long-press menu and ripple shape clipChatItem clipped the bubble shape with Modifier.clip. Modifier.clip of the bubble GenericShape mis-hit-tests its path on very tall items, so long-press on the lower part of a long message did not reach combinedClickable and the context menu did not open (#6991); on desktop the same clip also left the press ripple rendered as a rectangle. Clip the bubble GenericShape in the draw pass (drawWithCache + clipPath) instead: drawing is clipped identically, the press ripple included, with no effect on hit-test. The RoundRect shape (tail disabled) hit-tests correctly and keeps Modifier.clip. Fixes #6991 * plans: justify chat item long-press and ripple shape fix --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
co-authored by
Evgeny Poberezkin
parent
bf905eb545
commit
7548fdae3b
+20
-5
@@ -12,8 +12,10 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.drawWithCache
|
||||
import androidx.compose.ui.geometry.*
|
||||
import androidx.compose.ui.graphics.*
|
||||
import androidx.compose.ui.graphics.drawscope.clipPath
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.*
|
||||
@@ -1224,12 +1226,25 @@ fun Modifier.clipChatItem(chatItem: ChatItem? = null, tailVisible: Boolean = fal
|
||||
val style = shapeStyle(chatItem, chatItemTail.value, tailVisible, revealed)
|
||||
val cornerRoundness = chatItemRoundness.value.coerceIn(0f, 1f)
|
||||
|
||||
val shape = when (style) {
|
||||
is ShapeStyle.Bubble -> chatItemShape(cornerRoundness, LocalDensity.current, style.tailVisible, chatItem?.chatDir?.sent == true)
|
||||
is ShapeStyle.RoundRect -> RoundedCornerShape(style.radius * cornerRoundness)
|
||||
return when (style) {
|
||||
is ShapeStyle.Bubble -> {
|
||||
// Modifier.clip of the bubble GenericShape mis-hit-tests its path on very tall
|
||||
// items, dropping long-press on the lower part of the bubble (issue #6991). Clip
|
||||
// in the draw pass instead — drawing is clipped identically (the press ripple
|
||||
// included), with no effect on hit-test.
|
||||
val shape = chatItemShape(cornerRoundness, LocalDensity.current, style.tailVisible, chatItem?.chatDir?.sent == true)
|
||||
this.drawWithCache {
|
||||
val path = Path().apply {
|
||||
addOutline(shape.createOutline(size, layoutDirection, this@drawWithCache))
|
||||
}
|
||||
onDrawWithContent {
|
||||
clipPath(path) { this@onDrawWithContent.drawContent() }
|
||||
}
|
||||
}
|
||||
}
|
||||
// RoundRect hit-tests correctly — no bug here, keep the antialiased Modifier.clip.
|
||||
is ShapeStyle.RoundRect -> this.clip(RoundedCornerShape(style.radius * cornerRoundness))
|
||||
}
|
||||
|
||||
return this.clip(shape)
|
||||
}
|
||||
|
||||
private fun chatItemShape(roundness: Float, density: Density, tailVisible: Boolean, sent: Boolean = false): GenericShape = GenericShape { size, _ ->
|
||||
|
||||
Reference in New Issue
Block a user