From 88d11aafec809398915791ddc8b98bd5033065d6 Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Sat, 21 Mar 2026 09:25:23 -0500 Subject: [PATCH] fix: Update messaging feature with contact item keys and MQTT limits (#4871) --- .../org/meshtastic/core/database/dao/PacketDao.kt | 1 + .../core/network/repository/MQTTRepositoryImpl.kt | 14 +++++++++++++- .../feature/messaging/ui/contact/Contacts.kt | 5 +++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/core/database/src/commonMain/kotlin/org/meshtastic/core/database/dao/PacketDao.kt b/core/database/src/commonMain/kotlin/org/meshtastic/core/database/dao/PacketDao.kt index ae6506cbf..ba0f34056 100644 --- a/core/database/src/commonMain/kotlin/org/meshtastic/core/database/dao/PacketDao.kt +++ b/core/database/src/commonMain/kotlin/org/meshtastic/core/database/dao/PacketDao.kt @@ -76,6 +76,7 @@ interface PacketDao { ) latest ON p.contact_key = latest.contact_key AND p.received_time = latest.max_time WHERE (p.myNodeNum = 0 OR p.myNodeNum = (SELECT myNodeNum FROM my_node)) AND p.port_num = 1 AND p.filtered = 0 + GROUP BY p.contact_key ORDER BY p.received_time DESC """, ) diff --git a/core/network/src/commonMain/kotlin/org/meshtastic/core/network/repository/MQTTRepositoryImpl.kt b/core/network/src/commonMain/kotlin/org/meshtastic/core/network/repository/MQTTRepositoryImpl.kt index e6711f9db..aa0da5efc 100644 --- a/core/network/src/commonMain/kotlin/org/meshtastic/core/network/repository/MQTTRepositoryImpl.kt +++ b/core/network/src/commonMain/kotlin/org/meshtastic/core/network/repository/MQTTRepositoryImpl.kt @@ -32,6 +32,8 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Semaphore +import kotlinx.coroutines.sync.withPermit import kotlinx.serialization.json.Json import okio.ByteString.Companion.toByteString import org.koin.core.annotation.Single @@ -58,6 +60,7 @@ class MQTTRepositoryImpl( private val json = Json { ignoreUnknownKeys = true } private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob()) private var clientJob: Job? = null + private val publishSemaphore = Semaphore(20) override fun disconnect() { Logger.i { "MQTT Disconnecting" } @@ -162,6 +165,15 @@ class MQTTRepositoryImpl( @OptIn(ExperimentalUnsignedTypes::class) override fun publish(topic: String, data: ByteArray, retained: Boolean) { Logger.d { "MQTT publishing message to topic $topic (size: ${data.size} bytes, retained: $retained)" } - client?.publish(retain = retained, qos = Qos.AT_LEAST_ONCE, topic = topic, payload = data.toUByteArray()) + scope.launch { + publishSemaphore.withPermit { + client?.publish( + retain = retained, + qos = Qos.AT_LEAST_ONCE, + topic = topic, + payload = data.toUByteArray(), + ) + } + } } } diff --git a/feature/messaging/src/androidMain/kotlin/org/meshtastic/feature/messaging/ui/contact/Contacts.kt b/feature/messaging/src/androidMain/kotlin/org/meshtastic/feature/messaging/ui/contact/Contacts.kt index e002459c7..028b5be82 100644 --- a/feature/messaging/src/androidMain/kotlin/org/meshtastic/feature/messaging/ui/contact/Contacts.kt +++ b/feature/messaging/src/androidMain/kotlin/org/meshtastic/feature/messaging/ui/contact/Contacts.kt @@ -57,6 +57,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems +import androidx.paging.compose.itemKey import com.google.accompanist.permissions.ExperimentalPermissionsApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest @@ -566,7 +567,7 @@ private fun LazyListScope.contactListPlaceholdersItems( channels: ChannelSet?, haptic: HapticFeedback, ) { - items(count = placeholders.size, key = { index -> placeholders[index].contactKey }) { index -> + items(count = placeholders.size, key = { index -> "${placeholders[index].contactKey}_placeholder" }) { index -> val contact = placeholders[index] ContactItem( contact = contact, @@ -593,7 +594,7 @@ private fun LazyListScope.contactListPagedItems( channels: ChannelSet?, haptic: HapticFeedback, ) { - items(count = contacts.itemCount, key = { index -> contacts[index]?.contactKey ?: index }) { index -> + items(count = contacts.itemCount, key = contacts.itemKey { it.contactKey }) { index -> contacts[index]?.let { contact -> ContactItem( contact = contact,