feat: add context menu for chat message #43
@@ -107,7 +107,11 @@ fun rememberMessageUiModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ChatMessage(model: MessageUiModel, onLongClick: (Rect) -> Unit = {}) {
|
fun ChatMessage(
|
||||||
|
model: MessageUiModel,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onLongClick: (Rect) -> Unit = {}
|
||||||
|
) {
|
||||||
var isMessageClicked by remember { mutableStateOf(false) }
|
var isMessageClicked by remember { mutableStateOf(false) }
|
||||||
var layoutCoordinates by remember { mutableStateOf<LayoutCoordinates?>(null) }
|
var layoutCoordinates by remember { mutableStateOf<LayoutCoordinates?>(null) }
|
||||||
|
|
||||||
@@ -124,10 +128,10 @@ fun ChatMessage(model: MessageUiModel, onLongClick: (Rect) -> Unit = {}) {
|
|||||||
if (!model.isMine) MaterialTheme.colorScheme.onSurface else MaterialTheme.colorScheme.onPrimaryContainer
|
if (!model.isMine) MaterialTheme.colorScheme.onSurface else MaterialTheme.colorScheme.onPrimaryContainer
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = modifier
|
||||||
|
.onGloballyPositioned { layoutCoordinates = it }
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 4.dp)
|
.padding(vertical = 4.dp),
|
||||||
.onGloballyPositioned { layoutCoordinates = it },
|
|
||||||
contentAlignment = if (model.isMine) Alignment.CenterEnd else Alignment.CenterStart
|
contentAlignment = if (model.isMine) Alignment.CenterEnd else Alignment.CenterStart
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.blur
|
import androidx.compose.ui.draw.blur
|
||||||
import androidx.compose.ui.geometry.Rect
|
import androidx.compose.ui.geometry.Rect
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalWindowInfo
|
import androidx.compose.ui.platform.LocalWindowInfo
|
||||||
@@ -277,8 +278,14 @@ fun ChatScreen(
|
|||||||
currentUserPublicKey = currentUser?.publicKey,
|
currentUserPublicKey = currentUser?.publicKey,
|
||||||
contentColor = if (isMine) mineColor else otherColor
|
contentColor = if (isMine) mineColor else otherColor
|
||||||
)
|
)
|
||||||
|
val isHighlighted =
|
||||||
|
selectedMessage?.first?.id == uiModel.id
|
||||||
|
|
||||||
ChatMessage(
|
ChatMessage(
|
||||||
model = uiModel,
|
model = uiModel,
|
||||||
|
modifier = Modifier.graphicsLayer {
|
||||||
|
alpha = if (isHighlighted) 0f else 1f
|
||||||
|
},
|
||||||
onLongClick = { rect ->
|
onLongClick = { rect ->
|
||||||
selectedMessage = uiModel to rect
|
selectedMessage = uiModel to rect
|
||||||
}
|
}
|
||||||
@@ -419,27 +426,27 @@ fun ChatScreen(
|
|||||||
val contentBottomDp = with(density) { (bounds.bottom + totalExtraHeightPx).toDp() }
|
val contentBottomDp = with(density) { (bounds.bottom + totalExtraHeightPx).toDp() }
|
||||||
Spacer(modifier = Modifier.height(contentBottomDp + 200.dp))
|
Spacer(modifier = Modifier.height(contentBottomDp + 200.dp))
|
||||||
|
|
||||||
Column(
|
ChatMessage(
|
||||||
|
model = model,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.offset {
|
.offset { IntOffset(0, bounds.top.toInt()) }
|
||||||
IntOffset(
|
.padding(horizontal = 16.dp)
|
||||||
0,
|
)
|
||||||
if (showAbove) (bounds.top - totalExtraHeightPx).toInt()
|
|
||||||
.coerceAtLeast(0) else bounds.top.toInt()
|
val menuOffset = if (showAbove) {
|
||||||
)
|
bounds.top - totalExtraHeightPx
|
||||||
}
|
} else {
|
||||||
|
bounds.bottom + with(density) { 12.dp.toPx() } // 12dp spacing below
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.offset { IntOffset(0, menuOffset.toInt().coerceAtLeast(0)) }
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
horizontalAlignment = if (model.isMine) Alignment.End else Alignment.Start,
|
contentAlignment = if (model.isMine) Alignment.CenterEnd else Alignment.CenterStart
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
|
||||||
) {
|
) {
|
||||||
if (showAbove) {
|
ContextMenu { selectedMessage = null }
|
||||||
ContextMenu { selectedMessage = null }
|
|
||||||
ChatMessage(model = model)
|
|
||||||
} else {
|
|
||||||
ChatMessage(model = model)
|
|
||||||
ContextMenu { selectedMessage = null }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user