add scroll to message
This commit is contained in:
@@ -90,6 +90,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.jetbrains.compose.resources.painterResource
|
import org.jetbrains.compose.resources.painterResource
|
||||||
|
import rust.nostr.sdk.EventId
|
||||||
import rust.nostr.sdk.UnsignedEvent
|
import rust.nostr.sdk.UnsignedEvent
|
||||||
import su.reya.coop.LocalNavigator
|
import su.reya.coop.LocalNavigator
|
||||||
import su.reya.coop.LocalProfileCache
|
import su.reya.coop.LocalProfileCache
|
||||||
@@ -161,6 +162,29 @@ fun ChatScreen(
|
|||||||
label = "blurAnimation"
|
label = "blurAnimation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val goToMessage = { eventId: EventId? ->
|
||||||
|
if (eventId != null) {
|
||||||
|
scope.launch {
|
||||||
|
var targetIndex = -1
|
||||||
|
var currentIndex = 0
|
||||||
|
|
||||||
|
for (group in groupedMessages.value) {
|
||||||
|
val msgInGroup = group.value
|
||||||
|
val idx = msgInGroup.indexOfFirst { it.id() == eventId }
|
||||||
|
if (idx != -1) {
|
||||||
|
targetIndex = currentIndex + idx
|
||||||
|
break
|
||||||
|
}
|
||||||
|
currentIndex += msgInGroup.size + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetIndex != -1) {
|
||||||
|
listState.animateScrollToItem(targetIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val sendFile = { uri: Uri ->
|
val sendFile = { uri: Uri ->
|
||||||
scope.launch {
|
scope.launch {
|
||||||
// Read file on IO dispatcher
|
// Read file on IO dispatcher
|
||||||
@@ -196,9 +220,7 @@ fun ChatScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Box(
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
modifier = Modifier.fillMaxSize()
|
|
||||||
) {
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.blur(blurAmount),
|
modifier = Modifier.blur(blurAmount),
|
||||||
contentWindowInsets = ScaffoldDefaults.contentWindowInsets.union(WindowInsets.ime),
|
contentWindowInsets = ScaffoldDefaults.contentWindowInsets.union(WindowInsets.ime),
|
||||||
@@ -303,7 +325,13 @@ fun ChatScreen(
|
|||||||
.animateItem(),
|
.animateItem(),
|
||||||
verticalArrangement = Arrangement.spacedBy(2.dp)
|
verticalArrangement = Arrangement.spacedBy(2.dp)
|
||||||
) {
|
) {
|
||||||
replyPreview?.let { ReplyPreview(it, model.isMine) }
|
replyPreview?.let { previewEvent ->
|
||||||
|
ReplyPreview(
|
||||||
|
event = previewEvent,
|
||||||
|
isMine = model.isMine,
|
||||||
|
onClick = { goToMessage(previewEvent.id()) }
|
||||||
|
)
|
||||||
|
}
|
||||||
ChatMessage(
|
ChatMessage(
|
||||||
model = model,
|
model = model,
|
||||||
modifier = Modifier.graphicsLayer {
|
modifier = Modifier.graphicsLayer {
|
||||||
@@ -545,7 +573,11 @@ private fun ReplyBox(model: MessageModel, onDismiss: () -> Unit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ReplyPreview(event: UnsignedEvent, isMine: Boolean = false) {
|
private fun ReplyPreview(
|
||||||
|
event: UnsignedEvent,
|
||||||
|
isMine: Boolean = false,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
val profileCache = LocalProfileCache.current
|
val profileCache = LocalProfileCache.current
|
||||||
val profileFlow = remember(event) { profileCache.getMetadata(event.author()) }
|
val profileFlow = remember(event) { profileCache.getMetadata(event.author()) }
|
||||||
val profile by profileFlow.collectAsStateWithLifecycle()
|
val profile by profileFlow.collectAsStateWithLifecycle()
|
||||||
@@ -561,7 +593,9 @@ private fun ReplyPreview(event: UnsignedEvent, isMine: Boolean = false) {
|
|||||||
contentAlignment = if (isMine) Alignment.CenterEnd else Alignment.CenterStart
|
contentAlignment = if (isMine) Alignment.CenterEnd else Alignment.CenterStart
|
||||||
) {
|
) {
|
||||||
Surface(
|
Surface(
|
||||||
modifier = Modifier.widthIn(max = 280.dp),
|
modifier = Modifier
|
||||||
|
.widthIn(max = 280.dp)
|
||||||
|
.clickable(onClick = onClick),
|
||||||
color = MaterialTheme.colorScheme.tertiaryContainer,
|
color = MaterialTheme.colorScheme.tertiaryContainer,
|
||||||
shape = bubbleShape,
|
shape = bubbleShape,
|
||||||
) {
|
) {
|
||||||
@@ -569,13 +603,13 @@ private fun ReplyPreview(event: UnsignedEvent, isMine: Boolean = false) {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(2.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = profile?.name ?: "Unknown",
|
text = profile?.name ?: "Unknown",
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = MaterialTheme.colorScheme.onTertiaryContainer.copy(
|
fontWeight = FontWeight.SemiBold,
|
||||||
alpha = 0.6f
|
color = MaterialTheme.colorScheme.onTertiaryContainer,
|
||||||
),
|
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = event.content(),
|
text = event.content(),
|
||||||
|
|||||||
Reference in New Issue
Block a user