From 500ae49b2c7fef926f5bd2eb5e4d73c46a284028 Mon Sep 17 00:00:00 2001
From: Mac DeCourcy <49794076+mdecourcy@users.noreply.github.com>
Date: Wed, 26 Nov 2025 15:44:35 -0800
Subject: [PATCH] fix: loadCachedDb() before backfill to ensure in-mem nodedb
isn't stale, show filtered count in nodelist (#3827)
---
.../java/com/geeksville/mesh/service/MeshService.kt | 10 +++++++---
.../src/commonMain/composeResources/values/strings.xml | 2 +-
.../meshtastic/feature/messaging/MessageListPaged.kt | 1 +
.../org/meshtastic/feature/node/list/NodeListScreen.kt | 2 +-
4 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
index 395b420d7..12946a2d8 100644
--- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
+++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt
@@ -410,7 +410,7 @@ class MeshService : Service() {
}
.launchIn(serviceScope)
- loadSettings() // Load our last known node DB
+ loadCachedNodeDB() // Load our last known node DB
// the rest of our init will happen once we are in radioConnection.onServiceConnected
}
@@ -482,7 +482,7 @@ class MeshService : Service() {
// BEGINNING OF MODEL - FIXME, move elsewhere
//
- private fun loadSettings() = serviceScope.handledLaunch {
+ private fun loadCachedNodeDB() = serviceScope.handledLaunch {
myNodeInfo = nodeRepository.myNodeInfo.value
nodeDBbyNodeNum.putAll(nodeRepository.getNodeDBbyNum().first())
// Note: we do not haveNodeDB = true because that means we've got a valid db from a real
@@ -2104,7 +2104,9 @@ class MeshService : Service() {
} else {
newNodes.forEach(::installNodeInfo)
newNodes.clear()
- serviceScope.handledLaunch { nodeRepository.installConfig(myNodeInfo!!, nodeDBbyNodeNum.values.toList()) }
+ // Individual nodes are already upserted to DB via updateNodeInfo->nodeRepository.upsert
+ // Only call installConfig to persist myNodeInfo, not to overwrite all nodes
+ serviceScope.handledLaunch { myNodeInfo?.let { nodeRepository.installConfig(it, emptyList()) } }
haveNodeDB = true
flushEarlyReceivedPackets("node_info_complete")
sendAnalytics()
@@ -2310,6 +2312,8 @@ class MeshService : Service() {
historyLog { dbSummary }
// Do not clear packet DB here; messages are per-device and should persist
clearNotifications()
+ // Reload nodes from the newly switched database
+ loadCachedNodeDB()
}
} else {
Timber.d("SetDeviceAddress: Device address is unchanged, ignoring.")
diff --git a/core/strings/src/commonMain/composeResources/values/strings.xml b/core/strings/src/commonMain/composeResources/values/strings.xml
index 365eee340..8b21c934e 100644
--- a/core/strings/src/commonMain/composeResources/values/strings.xml
+++ b/core/strings/src/commonMain/composeResources/values/strings.xml
@@ -774,7 +774,7 @@
Modules unlocked
Modules already unlocked
Remote
- (%1$d online / %2$d total)
+ (%1$d online / %2$d shown / %3$d total)
React
Disconnect
Scanning for Bluetooth devices…
diff --git a/feature/messaging/src/main/kotlin/org/meshtastic/feature/messaging/MessageListPaged.kt b/feature/messaging/src/main/kotlin/org/meshtastic/feature/messaging/MessageListPaged.kt
index a0d4ed1f7..78ef0eda6 100644
--- a/feature/messaging/src/main/kotlin/org/meshtastic/feature/messaging/MessageListPaged.kt
+++ b/feature/messaging/src/main/kotlin/org/meshtastic/feature/messaging/MessageListPaged.kt
@@ -367,6 +367,7 @@ private fun UpdateUnreadCountPaged(
}
.debounce(timeoutMillis = UnreadUiDefaults.SCROLL_DEBOUNCE_MILLIS)
.collectLatest { index ->
+ // Only mark messages as read if we have a valid index (screen is visible and not scrolling)
if (index != null) {
val lastUnreadIndex = findLastUnreadMessageIndex(messages)
// If we're at/past the oldest unread, mark the first visible unread message
diff --git a/feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListScreen.kt b/feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListScreen.kt
index c17765093..0c99acc88 100644
--- a/feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListScreen.kt
+++ b/feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListScreen.kt
@@ -122,7 +122,7 @@ fun NodeListScreen(
topBar = {
MainAppBar(
title = stringResource(Res.string.nodes),
- subtitle = stringResource(Res.string.node_count_template, onlineNodeCount, totalNodeCount),
+ subtitle = stringResource(Res.string.node_count_template, onlineNodeCount, nodes.size, totalNodeCount),
ourNode = ourNode,
showNodeChip = false,
canNavigateUp = false,