112 lines
3.8 KiB
Kotlin
112 lines
3.8 KiB
Kotlin
package io.element.android.x.features.messages.components
|
|
|
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
import androidx.compose.foundation.combinedClickable
|
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
import androidx.compose.foundation.layout.offset
|
|
import androidx.compose.foundation.layout.widthIn
|
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
import androidx.compose.material.ripple.rememberRipple
|
|
import androidx.compose.material3.Surface
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.draw.clip
|
|
import androidx.compose.ui.graphics.Shape
|
|
import androidx.compose.ui.unit.dp
|
|
import io.element.android.x.designsystem.LocalIsDarkTheme
|
|
import io.element.android.x.designsystem.MessageHighlightDark
|
|
import io.element.android.x.designsystem.MessageHighlightLight
|
|
import io.element.android.x.designsystem.SystemGrey5Dark
|
|
import io.element.android.x.designsystem.SystemGrey5Light
|
|
import io.element.android.x.designsystem.SystemGrey6Dark
|
|
import io.element.android.x.designsystem.SystemGrey6Light
|
|
import io.element.android.x.features.messages.model.MessagesItemGroupPosition
|
|
|
|
private val BUBBLE_RADIUS = 16.dp
|
|
|
|
@OptIn(ExperimentalFoundationApi::class)
|
|
@Composable
|
|
fun MessageEventBubble(
|
|
groupPosition: MessagesItemGroupPosition,
|
|
isMine: Boolean,
|
|
interactionSource: MutableInteractionSource,
|
|
isHighlighted: Boolean,
|
|
modifier: Modifier = Modifier,
|
|
onClick: () -> Unit,
|
|
onLongClick: () -> Unit,
|
|
content: @Composable () -> Unit,
|
|
) {
|
|
fun bubbleShape(): Shape {
|
|
return when (groupPosition) {
|
|
MessagesItemGroupPosition.First -> if (isMine) {
|
|
RoundedCornerShape(BUBBLE_RADIUS, BUBBLE_RADIUS, 0.dp, BUBBLE_RADIUS)
|
|
} else {
|
|
RoundedCornerShape(BUBBLE_RADIUS, BUBBLE_RADIUS, BUBBLE_RADIUS, 0.dp)
|
|
}
|
|
MessagesItemGroupPosition.Middle -> if (isMine) {
|
|
RoundedCornerShape(BUBBLE_RADIUS, 0.dp, 0.dp, BUBBLE_RADIUS)
|
|
} else {
|
|
RoundedCornerShape(0.dp, BUBBLE_RADIUS, BUBBLE_RADIUS, 0.dp)
|
|
}
|
|
MessagesItemGroupPosition.Last -> if (isMine) {
|
|
RoundedCornerShape(BUBBLE_RADIUS, 0.dp, BUBBLE_RADIUS, BUBBLE_RADIUS)
|
|
} else {
|
|
RoundedCornerShape(0.dp, BUBBLE_RADIUS, BUBBLE_RADIUS, BUBBLE_RADIUS)
|
|
}
|
|
MessagesItemGroupPosition.None ->
|
|
RoundedCornerShape(
|
|
BUBBLE_RADIUS,
|
|
BUBBLE_RADIUS,
|
|
BUBBLE_RADIUS,
|
|
BUBBLE_RADIUS
|
|
)
|
|
}
|
|
}
|
|
|
|
fun Modifier.offsetForItem(): Modifier {
|
|
return if (isMine) {
|
|
offset(y = -(12.dp))
|
|
} else {
|
|
offset(x = 20.dp, y = -(12.dp))
|
|
}
|
|
}
|
|
|
|
val backgroundBubbleColor = if (isHighlighted) {
|
|
if (LocalIsDarkTheme.current) {
|
|
MessageHighlightDark
|
|
} else {
|
|
MessageHighlightLight
|
|
}
|
|
} else {
|
|
if (isMine) {
|
|
if (LocalIsDarkTheme.current) {
|
|
SystemGrey5Dark
|
|
} else {
|
|
SystemGrey5Light
|
|
}
|
|
} else {
|
|
if (LocalIsDarkTheme.current) {
|
|
SystemGrey6Dark
|
|
} else {
|
|
SystemGrey6Light
|
|
}
|
|
}
|
|
}
|
|
val bubbleShape = bubbleShape()
|
|
Surface(
|
|
modifier = modifier
|
|
.widthIn(min = 80.dp)
|
|
.offsetForItem()
|
|
.clip(bubbleShape)
|
|
.combinedClickable(
|
|
onClick = onClick,
|
|
onLongClick = onLongClick,
|
|
indication = rememberRipple(),
|
|
interactionSource = interactionSource
|
|
),
|
|
color = backgroundBubbleColor,
|
|
shape = bubbleShape,
|
|
content = content
|
|
)
|
|
}
|