commit 14ba7f27ec5e8cb20b6ea8651c5147e488102c0e
parent 4f2dfbeb8a027445e99af3f7785ebffd560f4940
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sat, 30 Mar 2024 17:11:51 +0100

fix: messaging preview crash

Diffstat:
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/MessagingPreview.kt | 80+++++++++++++++++++++++++++++++++++--------------------------------------------
1 file changed, 35 insertions(+), 45 deletions(-)

diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/MessagingPreview.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/social/MessagingPreview.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons @@ -40,7 +41,6 @@ import me.rhunk.snapenhance.messaging.MessagingTaskConstraint import me.rhunk.snapenhance.messaging.MessagingTaskType import me.rhunk.snapenhance.ui.manager.Routes import me.rhunk.snapenhance.ui.util.Dialog -import java.util.SortedMap class MessagingPreview: Routes.Route() { private lateinit var coroutineScope: CoroutineScope @@ -50,8 +50,7 @@ class MessagingPreview: Routes.Route() { private val myUserId by lazy { messagingBridge.myUserId } private val contentTypeTranslation by lazy { context.translation.getCategory("content_type") } - private var messages = sortedMapOf<Long, Message>() - private var messageSize by mutableIntStateOf(0) + private var messages = mutableStateListOf<Message>() private var conversationId by mutableStateOf<String?>(null) private val selectedMessages = mutableStateListOf<Long>() // client message id @@ -310,8 +309,7 @@ class MessagingPreview: Routes.Route() { ActionButton(text = if (hasSelection) "Delete selected" else "Delete all", icon = Icons.Rounded.DeleteForever) { launchMessagingTask(MessagingTaskType.DELETE, listOf(MessagingConstraints.USER_ID(myUserId))) { message -> coroutineScope.launch { - messages.remove(message.serverMessageId) - messageSize = messages.size + message.contentType = ContentType.STATUS.id } } if (hasSelection) runCurrentTask() @@ -323,8 +321,7 @@ class MessagingPreview: Routes.Route() { @Composable private fun ConversationPreview( - messages: SortedMap<Long, Message>, - messageSize: Int, + messages: List<Message>, fetchNewMessages: () -> Unit ) { DisposableEffect(Unit) { @@ -334,32 +331,13 @@ class MessagingPreview: Routes.Route() { } LazyColumn( + reverseLayout = true, modifier = Modifier - .fillMaxSize(), + .fillMaxWidth(), state = previewScrollState, ) { - item { - if (messages.isEmpty()) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(40.dp), - horizontalArrangement = Arrangement.Center - ) { - Text("No messages") - } - } - Spacer(modifier = Modifier.height(20.dp)) - - LaunchedEffect(Unit) { - if (messages.size > 0) { - fetchNewMessages() - } - } - } - items(messageSize) {index -> - val elementKey = remember(index) { messages.entries.elementAt(index).value.clientMessageId } - val messageReader = ProtoReader(messages.entries.elementAt(index).value.content) + items(messages, key = { it.serverMessageId }) {message -> + val messageReader = remember(message.contentType) { ProtoReader(message.content) } val contentType = ContentType.fromMessageContainer(messageReader) Card( @@ -369,25 +347,44 @@ class MessagingPreview: Routes.Route() { if (contentType == ContentType.STATUS) return@pointerInput detectTapGestures( onLongPress = { - toggleSelectedMessage(elementKey) + toggleSelectedMessage(message.clientMessageId) }, onTap = { if (selectedMessages.isNotEmpty()) { - toggleSelectedMessage(elementKey) + toggleSelectedMessage(message.clientMessageId) } } ) }, colors = CardDefaults.cardColors( - containerColor = if (selectedMessages.contains(elementKey)) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surfaceVariant + containerColor = if (selectedMessages.contains(message.clientMessageId)) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surfaceVariant ), ) { + val contentMessage = remember(message.contentType) { "[${contentType?.let { contentTypeTranslation.getOrNull(it.name) ?: it.name } }] ${messageReader.getString(2, 1) ?: "" }" } Row( modifier = Modifier .padding(5.dp) ) { + Text(contentMessage) + } + } + } + item { + if (messages.isEmpty()) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(40.dp), + horizontalArrangement = Arrangement.Center + ) { + Text("No messages") + } + } + Spacer(modifier = Modifier.height(20.dp)) - Text("[${contentType?.let { contentTypeTranslation.getOrNull(it.name) ?: it.name } }] ${messageReader.getString(2, 1) ?: ""}") + LaunchedEffect(Unit) { + if (messages.isNotEmpty()) { + fetchNewMessages() } } } @@ -431,7 +428,7 @@ class MessagingPreview: Routes.Route() { conversationId!!, 20, lastMessageId - ) + )?.reversed() if (queriedMessages == null) { context.shortToast("Failed to fetch messages") @@ -439,19 +436,13 @@ class MessagingPreview: Routes.Route() { } withContext(Dispatchers.Main) { - messages.putAll(queriedMessages.map { it.serverMessageId to it }) - messageSize = messages.size - if (queriedMessages.isNotEmpty()) { - lastMessageId = queriedMessages.first().clientMessageId - delay(20) - previewScrollState.scrollToItem(queriedMessages.size - 1) - } + messages.addAll(queriedMessages) + lastMessageId = queriedMessages.lastOrNull()?.clientMessageId ?: lastMessageId } }.onFailure { context.log.error("Failed to fetch messages", it) context.shortToast("Failed to fetch messages: ${it.message}") } - context.log.verbose("fetched ${messages.size} messages") } } @@ -490,7 +481,6 @@ class MessagingPreview: Routes.Route() { LaunchedEffect(Unit) { messages.clear() - messageSize = 0 conversationId = null isBridgeConnected = context.hasMessagingBridge() @@ -529,7 +519,7 @@ class MessagingPreview: Routes.Route() { } if (isBridgeConnected && !hasBridgeError) { - ConversationPreview(messages, messageSize, ::fetchNewMessages) + ConversationPreview(messages, ::fetchNewMessages) } } }