Skip to content

Commit 1c0dc48

Browse files
authored
fix: node search by keeping denormalized name columns up to date and backfilling existing nodes (#3839)
1 parent ef9c0dc commit 1c0dc48

File tree

5 files changed

+44
-1
lines changed

5 files changed

+44
-1
lines changed

core/data/src/main/kotlin/org/meshtastic/core/data/datasource/NodeInfoWriteDataSource.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,6 @@ interface NodeInfoWriteDataSource {
3737
suspend fun upsert(metadata: MetadataEntity)
3838

3939
suspend fun setNodeNotes(num: Int, notes: String)
40+
41+
suspend fun backfillDenormalizedNames()
4042
}

core/data/src/main/kotlin/org/meshtastic/core/data/datasource/SwitchingNodeInfoWriteDataSource.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,7 @@ constructor(
5757

5858
override suspend fun setNodeNotes(num: Int, notes: String) =
5959
withContext(dispatchers.io) { dbManager.withDb { it.nodeInfoDao().setNodeNotes(num, notes) } }
60+
61+
override suspend fun backfillDenormalizedNames() =
62+
withContext(dispatchers.io) { dbManager.withDb { it.nodeInfoDao().backfillDenormalizedNames() } }
6063
}

core/data/src/main/kotlin/org/meshtastic/core/data/repository/NodeRepository.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ constructor(
5454
private val nodeInfoWriteDataSource: NodeInfoWriteDataSource,
5555
private val dispatchers: CoroutineDispatchers,
5656
) {
57+
init {
58+
// Backfill denormalized name columns for existing nodes on startup
59+
processLifecycle.coroutineScope.launchWhenCreated {
60+
withContext(dispatchers.io) { nodeInfoWriteDataSource.backfillDenormalizedNames() }
61+
}
62+
}
63+
5764
// hardware info about our local device (can be null)
5865
val myNodeInfo: StateFlow<MyNodeEntity?> =
5966
nodeInfoReadDataSource

core/database/src/main/kotlin/org/meshtastic/core/database/dao/NodeInfoDao.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import org.meshtastic.core.database.entity.MetadataEntity
3030
import org.meshtastic.core.database.entity.MyNodeEntity
3131
import org.meshtastic.core.database.entity.NodeEntity
3232
import org.meshtastic.core.database.entity.NodeWithRelations
33+
import org.meshtastic.proto.MeshProtos
3334

3435
@Suppress("TooManyFunctions")
3536
@Dao
@@ -49,6 +50,13 @@ interface NodeInfoDao {
4950
// and to support lazy migration.
5051
incomingNode.publicKey = incomingNode.user.publicKey
5152

53+
// Populate denormalized name columns from the User protobuf for search functionality
54+
// Only populate if the user is not a placeholder (hwModel != UNSET)
55+
if (incomingNode.user.hwModel != MeshProtos.HardwareModel.UNSET) {
56+
incomingNode.longName = incomingNode.user.longName
57+
incomingNode.shortName = incomingNode.user.shortName
58+
}
59+
5260
val existingNodeEntity = getNodeByNum(incomingNode.num)?.node
5361

5462
return if (existingNodeEntity == null) {
@@ -240,4 +248,27 @@ interface NodeInfoDao {
240248
setMyNodeInfo(mi)
241249
putAll(nodes.map { getVerifiedNodeForUpsert(it) })
242250
}
251+
252+
/**
253+
* Backfills longName and shortName columns from the user protobuf for nodes where these columns are NULL. This
254+
* ensures search functionality works for all nodes. Skips placeholder/default users (hwModel == UNSET).
255+
*/
256+
@Transaction
257+
fun backfillDenormalizedNames() {
258+
val nodes = getAllNodesSnapshot()
259+
val nodesToUpdate =
260+
nodes
261+
.filter { node ->
262+
// Only backfill if columns are NULL AND the user is not a placeholder (hwModel != UNSET)
263+
(node.longName == null || node.shortName == null) &&
264+
node.user.hwModel != MeshProtos.HardwareModel.UNSET
265+
}
266+
.map { node -> node.copy(longName = node.user.longName, shortName = node.user.shortName) }
267+
if (nodesToUpdate.isNotEmpty()) {
268+
putAll(nodesToUpdate)
269+
}
270+
}
271+
272+
@Query("SELECT * FROM nodes")
273+
fun getAllNodesSnapshot(): List<NodeEntity>
243274
}

feature/node/src/main/kotlin/org/meshtastic/feature/node/list/NodeListViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ constructor(
108108
)
109109
.map { list ->
110110
list
111-
.filter { it.isIgnored == filter.showIgnored }
111+
.filter { filter.showIgnored || !it.isIgnored }
112112
.filter { node ->
113113
if (filter.excludeInfrastructure) {
114114
val role = node.user.role

0 commit comments

Comments
 (0)