mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
@@ -598,7 +598,6 @@ fun ChatScreen(
|
|||||||
MessageContextMenu(
|
MessageContextMenu(
|
||||||
state = contextMenuState,
|
state = contextMenuState,
|
||||||
isAuthor = contextMenuState.message?.user_id == currentUserId,
|
isAuthor = contextMenuState.message?.user_id == currentUserId,
|
||||||
hazeState = hazeState,
|
|
||||||
screenWidthPx = screenWidthPx,
|
screenWidthPx = screenWidthPx,
|
||||||
screenHeightPx = screenHeightPx,
|
screenHeightPx = screenHeightPx,
|
||||||
onDismiss = { contextMenuState = contextMenuState.copy(isOpen = false) },
|
onDismiss = { contextMenuState = contextMenuState.copy(isOpen = false) },
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.graphics.TransformOrigin
|
import androidx.compose.ui.graphics.TransformOrigin
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
@@ -47,10 +46,6 @@ import androidx.compose.ui.unit.IntSize
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Popup
|
import androidx.compose.ui.window.Popup
|
||||||
import androidx.compose.ui.window.PopupProperties
|
import androidx.compose.ui.window.PopupProperties
|
||||||
import dev.chrisbanes.haze.HazeState
|
|
||||||
import dev.chrisbanes.haze.hazeEffect
|
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
|
||||||
import dev.chrisbanes.haze.materials.HazeMaterials
|
|
||||||
import ru.fromchat.api.Message
|
import ru.fromchat.api.Message
|
||||||
import ru.fromchat.ui.scaleOnPress
|
import ru.fromchat.ui.scaleOnPress
|
||||||
|
|
||||||
@@ -60,7 +55,6 @@ data class ContextMenuState(
|
|||||||
val position: IntOffset = IntOffset(0, 0)
|
val position: IntOffset = IntOffset(0, 0)
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptIn(ExperimentalHazeMaterialsApi::class)
|
|
||||||
@Suppress("AssignedValueIsNeverRead")
|
@Suppress("AssignedValueIsNeverRead")
|
||||||
@Composable
|
@Composable
|
||||||
fun MessageContextMenu(
|
fun MessageContextMenu(
|
||||||
@@ -70,7 +64,6 @@ fun MessageContextMenu(
|
|||||||
onReply: (Message) -> Unit,
|
onReply: (Message) -> Unit,
|
||||||
onEdit: (Message) -> Unit,
|
onEdit: (Message) -> Unit,
|
||||||
onDelete: (Message) -> Unit,
|
onDelete: (Message) -> Unit,
|
||||||
hazeState: HazeState,
|
|
||||||
screenWidthPx: Int,
|
screenWidthPx: Int,
|
||||||
screenHeightPx: Int,
|
screenHeightPx: Int,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
@@ -106,7 +99,6 @@ fun MessageContextMenu(
|
|||||||
if (shouldShowPopup && state.message != null) {
|
if (shouldShowPopup && state.message != null) {
|
||||||
var measuredSize by remember(state.message) { mutableStateOf(IntSize.Zero) }
|
var measuredSize by remember(state.message) { mutableStateOf(IntSize.Zero) }
|
||||||
|
|
||||||
// Off-screen measurement pass using a lightweight, non-animated version
|
|
||||||
SubcomposeLayout(Modifier.size(0.dp)) { _ ->
|
SubcomposeLayout(Modifier.size(0.dp)) { _ ->
|
||||||
val looseConstraints = Constraints(
|
val looseConstraints = Constraints(
|
||||||
minWidth = 0,
|
minWidth = 0,
|
||||||
@@ -206,7 +198,6 @@ fun MessageContextMenu(
|
|||||||
onDelete(it)
|
onDelete(it)
|
||||||
onDismiss()
|
onDismiss()
|
||||||
},
|
},
|
||||||
hazeState = hazeState,
|
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
animated = true,
|
animated = true,
|
||||||
scale = scale,
|
scale = scale,
|
||||||
@@ -219,7 +210,6 @@ fun MessageContextMenu(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalHazeMaterialsApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ContextMenuContent(
|
private fun ContextMenuContent(
|
||||||
message: Message,
|
message: Message,
|
||||||
@@ -229,7 +219,6 @@ private fun ContextMenuContent(
|
|||||||
onDelete: (Message) -> Unit,
|
onDelete: (Message) -> Unit,
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
animated: Boolean,
|
animated: Boolean,
|
||||||
hazeState: HazeState? = null,
|
|
||||||
withShadow: Boolean = true,
|
withShadow: Boolean = true,
|
||||||
scale: Float = 1f,
|
scale: Float = 1f,
|
||||||
alpha: Float = 1f,
|
alpha: Float = 1f,
|
||||||
@@ -246,10 +235,7 @@ private fun ContextMenuContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val baseModifier = modifier.width(IntrinsicSize.Max)
|
val baseModifier = modifier.width(IntrinsicSize.Max)
|
||||||
|
val containerModifier =
|
||||||
// Container that scales around the finger pivot and owns the material
|
|
||||||
// bounds (shape + clipping) so the blur region exactly matches the card.
|
|
||||||
val animatedContainerModifier =
|
|
||||||
if (animated) {
|
if (animated) {
|
||||||
baseModifier.graphicsLayer(
|
baseModifier.graphicsLayer(
|
||||||
scaleX = scale,
|
scaleX = scale,
|
||||||
@@ -268,59 +254,37 @@ private fun ContextMenuContent(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blur matches the material bounds from the parent, without its own transforms.
|
val menuColor = MaterialTheme.colorScheme.surfaceContainer
|
||||||
// Use a prebuilt material style, but with a transparent container color so we
|
|
||||||
// only get the blur characteristics, not an extra color wash.
|
|
||||||
val blurModifier =
|
|
||||||
if (hazeState != null) {
|
|
||||||
Modifier.hazeEffect(
|
|
||||||
state = hazeState,
|
|
||||||
style = HazeMaterials.thin(containerColor = Color.Transparent)
|
|
||||||
) {
|
|
||||||
noiseFactor = 0f
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Modifier
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fully transparent tint so we only see the material blur underneath.
|
|
||||||
val contentBackgroundColor = MaterialTheme.colorScheme.surface.copy(alpha = 0f)
|
|
||||||
val edgePadding = 8.dp
|
val edgePadding = 8.dp
|
||||||
val itemSpacing = 2.dp
|
val itemSpacing = 2.dp
|
||||||
|
|
||||||
Box(modifier = animatedContainerModifier) {
|
Box(modifier = containerModifier) {
|
||||||
Box(
|
Box(modifier = Modifier.matchParentSize().background(menuColor, menuShape))
|
||||||
modifier = blurModifier
|
Column(
|
||||||
.background(contentBackgroundColor)
|
modifier = Modifier
|
||||||
|
.padding(horizontal = edgePadding, vertical = edgePadding)
|
||||||
|
.verticalScroll(menuScrollState),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(itemSpacing)
|
||||||
) {
|
) {
|
||||||
Column(
|
ContextMenuItem(
|
||||||
modifier = Modifier
|
icon = Icons.AutoMirrored.Filled.Reply,
|
||||||
.padding(horizontal = edgePadding, vertical = edgePadding)
|
text = "Reply",
|
||||||
.verticalScroll(menuScrollState),
|
onClick = { onReply(message) }
|
||||||
verticalArrangement = Arrangement.spacedBy(itemSpacing)
|
)
|
||||||
) {
|
if (isAuthor) {
|
||||||
ContextMenuItem(
|
ContextMenuItem(
|
||||||
icon = Icons.AutoMirrored.Filled.Reply,
|
icon = Icons.Default.Edit,
|
||||||
text = "Reply",
|
text = "Edit",
|
||||||
onClick = {
|
onClick = { onEdit(message) }
|
||||||
onReply(message)
|
)
|
||||||
}
|
}
|
||||||
|
if (isAuthor) {
|
||||||
|
ContextMenuItem(
|
||||||
|
icon = Icons.Default.Delete,
|
||||||
|
text = "Delete",
|
||||||
|
onClick = { onDelete(message) },
|
||||||
|
isError = true
|
||||||
)
|
)
|
||||||
if (isAuthor) {
|
|
||||||
ContextMenuItem(
|
|
||||||
icon = Icons.Default.Edit,
|
|
||||||
text = "Edit",
|
|
||||||
onClick = { onEdit(message) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (isAuthor) {
|
|
||||||
ContextMenuItem(
|
|
||||||
icon = Icons.Default.Delete,
|
|
||||||
text = "Delete",
|
|
||||||
onClick = { onDelete(message) },
|
|
||||||
isError = true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user