Skip to content
Snippets Groups Projects
Verified Commit 29849e49 authored by Mikolai Gütschow's avatar Mikolai Gütschow
Browse files

mark messages shown on screen as read

parent c6e2da49
No related branches found
No related tags found
1 merge request!46Proper contact alias and (un)read messages handling
Pipeline #8359 passed
......@@ -45,4 +45,7 @@ data class ContactItem(
fun updateAlias(a: String?): ContactItem {
return copy(alias = a)
}
fun updateFromMessagesRead(c: Int): ContactItem =
copy(unread = unread - c)
}
......@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.event.Event
import org.briarproject.bramble.api.event.EventBus
import org.briarproject.briar.api.conversation.ConversationManager
import org.briarproject.briar.api.conversation.event.ConversationMessageTrackedEvent
import org.briarproject.briar.desktop.conversation.ConversationMessagesReadEvent
import javax.inject.Inject
class ContactListViewModel
......@@ -72,6 +73,10 @@ constructor(
is ContactAliasChangedEvent -> {
updateItem(e.contactId) { it.updateAlias(e.alias) }
}
is ConversationMessagesReadEvent -> {
LOG.info("${e.count} conversation messages read, updating item")
updateItem(e.contactId) { it.updateFromMessagesRead(e.count) }
}
}
}
}
package org.briarproject.briar.desktop.conversation
import org.briarproject.bramble.api.contact.ContactId
import org.briarproject.bramble.api.event.Event
/**
* An event that is broadcast when conversation messages
* are shown on the screen for the first time.
*/
data class ConversationMessagesReadEvent(
val count: Int,
val contactId: ContactId
) : Event()
......@@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
......@@ -55,6 +56,8 @@ fun ConversationScreen(
val (infoDrawer, setInfoDrawer) = remember { mutableStateOf(false) }
val (contactDrawerState, setDrawerState) = remember { mutableStateOf(ContactInfoDrawerState.MakeIntro) }
val scrollState = rememberLazyListState()
BoxWithConstraints(Modifier.fillMaxSize()) {
val animatedInfoDrawerOffsetX by animateDpAsState(if (infoDrawer) (-275).dp else 0.dp)
Scaffold(
......@@ -69,6 +72,7 @@ fun ConversationScreen(
content = { padding ->
LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp),
state = scrollState,
// reverseLayout to display most recent message (index 0) at the bottom
reverseLayout = true,
contentPadding = PaddingValues(8.dp),
......@@ -88,6 +92,14 @@ fun ConversationScreen(
)
},
)
if (viewModel.hasUnreadMessages.value) {
LaunchedEffect(scrollState.firstVisibleItemIndex) {
// mark all messages older than the first visible item as read
viewModel.markMessagesRead(scrollState.firstVisibleItemIndex)
}
}
if (infoDrawer) {
// TODO Find non-hacky way of setting scrim on entire app
Box(
......
package org.briarproject.briar.desktop.conversation
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import mu.KotlinLogging
......@@ -31,6 +32,7 @@ import org.briarproject.briar.api.messaging.PrivateMessageHeader
import org.briarproject.briar.desktop.contact.ContactItem
import org.briarproject.briar.desktop.utils.KLoggerUtils.logDuration
import org.briarproject.briar.desktop.utils.replaceIf
import org.briarproject.briar.desktop.utils.replaceIfIndexed
import org.briarproject.briar.desktop.viewmodel.BriarEventListenerViewModel
import java.util.Date
import javax.inject.Inject
......@@ -108,6 +110,18 @@ constructor(
}
}
val hasUnreadMessages = derivedStateOf { _messages.any { !it.isRead } }
fun markMessagesRead(untilIndex: Int) {
var count = 0
_messages.replaceIfIndexed({ idx, it -> idx >= untilIndex && !it.isRead }) { _, it ->
conversationManager.setReadFlag(it.groupId, it.id, true)
count++
it.markRead()
}
eventBus.broadcast(ConversationMessagesReadEvent(count, contactItem.value!!.contactId))
}
@Throws(DbException::class)
private fun createMessage(text: String): PrivateMessage {
val groupId = messagingManager.getConversationId(_contactItem.value!!.contactId)
......
......@@ -10,6 +10,18 @@ fun <T> MutableList<T>.replaceIf(predicate: (T) -> Boolean, transformation: (T)
}
}
fun <T> MutableList<T>.replaceIfIndexed(predicate: (Int, T) -> Boolean, transformation: (Int, T) -> T) {
val li = listIterator()
var index = 0
while (li.hasNext()) {
val n = li.next()
if (predicate(index, n)) {
li.set(transformation(index, n))
}
index++
}
}
fun <T> MutableList<T>.replaceFirst(predicate: (T) -> Boolean, transformation: (T) -> T) {
val li = listIterator()
while (li.hasNext()) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment