fix: unread count racecondition (#3784)

This commit is contained in:
Mac DeCourcy 2025-11-22 06:57:39 -08:00 committed by GitHub
parent f9575a2aec
commit 15481dd004
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 19 additions and 7 deletions

4
.gitignore vendored
View file

@ -41,3 +41,7 @@ keystore.properties
/build-logic/convention/build/*
/build-logic/build/
# Personal build scripts
build-and-install-android.sh
wireless-install.sh

View file

@ -61,6 +61,7 @@ import org.meshtastic.core.strings.Res
import org.meshtastic.core.strings.new_messages_below
import org.meshtastic.feature.messaging.component.MessageItem
import org.meshtastic.feature.messaging.component.ReactionDialog
import timber.log.Timber
import kotlin.collections.buildList
internal data class MessageListState(
@ -368,16 +369,23 @@ private fun UpdateUnreadCount(
messages: List<Message>,
onUnreadChanged: (Long, Long) -> Unit,
) {
LaunchedEffect(messages) {
val remoteMessageCount = remember(messages) { messages.count { !it.fromLocal } }
LaunchedEffect(remoteMessageCount, listState) {
Timber.d("UpdateUnreadCount LaunchedEffect started/restarted, remoteMessageCount=$remoteMessageCount")
snapshotFlow { listState.firstVisibleItemIndex }
.debounce(timeoutMillis = UnreadUiDefaults.SCROLL_DEBOUNCE_MILLIS)
.collectLatest { index ->
Timber.d("Debounce triggered, index=$index, messages.size=${messages.size}")
val lastUnreadIndex = messages.indexOfLast { !it.read && !it.fromLocal }
if (lastUnreadIndex != -1 && index <= lastUnreadIndex && index < messages.size) {
val visibleMessage = messages[index]
if (!visibleMessage.read && !visibleMessage.fromLocal) {
onUnreadChanged(visibleMessage.uuid, visibleMessage.receivedTime)
}
Timber.d("lastUnreadIndex=$lastUnreadIndex")
// If user has scrolled past all unread messages, mark the last unread message as read
if (lastUnreadIndex != -1 && index <= lastUnreadIndex) {
val lastUnreadMessage = messages[lastUnreadIndex]
Timber.d("Marking last unread message as read: ${lastUnreadMessage.uuid}")
onUnreadChanged(lastUnreadMessage.uuid, lastUnreadMessage.receivedTime)
} else {
Timber.d("Not marking as read - no unread messages or user hasn't scrolled past them")
}
}
}

View file

@ -45,5 +45,5 @@ internal object UnreadUiDefaults {
* A longer debounce prevents thrashing the database during quick scrubs yet still feels responsive once the user
* settles on a position.
*/
const val SCROLL_DEBOUNCE_MILLIS = 5_000L
const val SCROLL_DEBOUNCE_MILLIS = 3_000L
}