fix(auto): preserve raw channel index for shortcut/unread contactKey

Notifications and message routing key channel conversations by the raw
protocol channel index (e.g. "2^all"), but publishShortcuts and the
car screen were re-indexing after filtering out unnamed channels, so
named channels after a gap would never match their notification's
shortcutId/locusId and their unread badge would stay at zero.

Preserve the original index via mapIndexedNotNull { index to settings }.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
James Rich 2026-04-17 08:02:55 -05:00
parent 86bb9583b0
commit 36f770fd0b
3 changed files with 23 additions and 10 deletions

View file

@ -71,7 +71,7 @@ class MeshtasticCarScreen(carContext: CarContext) :
private var connectionState: ConnectionState = ConnectionState.Disconnected
private var favoriteNodes: List<Node> = emptyList()
private var channels: List<ChannelSettings> = emptyList()
private var channels: List<Pair<Int, ChannelSettings>> = emptyList()
private var unreadCounts: Map<String, Int> = emptyMap()
init {
@ -106,7 +106,9 @@ class MeshtasticCarScreen(carContext: CarContext) :
val channelsFlow =
radioConfigRepository.channelSetFlow
.map { cs ->
cs.settings.filterIndexed { index, settings -> index == 0 || settings.name.isNotEmpty() }
cs.settings.mapIndexedNotNull { index, settings ->
if (index == 0 || settings.name.isNotEmpty()) index to settings else null
}
}
.distinctUntilChanged()
@ -114,11 +116,8 @@ class MeshtasticCarScreen(carContext: CarContext) :
Triple(state, favorites, chs)
}
.flatMapLatest { (state, favorites, chs) ->
// Build per-conversation unread flows so the car screen invalidates
// on new messages, not just on topology/channel changes.
val contactKeys =
favorites.map { "0${it.user.id}" } +
chs.mapIndexed { i, _ -> "${i}${DataPacket.ID_BROADCAST}" }
favorites.map { "0${it.user.id}" } + chs.map { (i, _) -> "${i}${DataPacket.ID_BROADCAST}" }
if (contactKeys.isEmpty()) {
flowOf(Triple(state, favorites, chs) to emptyMap())
@ -204,7 +203,7 @@ class MeshtasticCarScreen(carContext: CarContext) :
private fun buildChannelsSection(): ItemList {
val builder = ItemList.Builder()
for ((index, channelSettings) in channels.take(MAX_LIST_ITEMS).withIndex()) {
for ((index, channelSettings) in channels.take(MAX_LIST_ITEMS)) {
val contactKey = "${index}${DataPacket.ID_BROADCAST}"
val unread = unreadCounts[contactKey] ?: 0
val channelName = channelSettings.name.ifEmpty { "Primary Channel" }