diff --git a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationViewModel.kt b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationViewModel.kt index 857f736f317ee56fdf61c63820b5930490cd0965..1b0cae45c3323ff9e24e3b9a0dc855d98646b8d5 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationViewModel.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationViewModel.kt @@ -64,14 +64,6 @@ constructor( private val LOG = KotlinLogging.logger {} } - private val conversationVisitor = derivedStateOf { - val c = _contactItem.value - if (c != null) - ConversationVisitor(c.name, ::loadMessageText) - else - null - } - private val _contactId = mutableStateOf<ContactId?>(null) private val _contactItem = mutableStateOf<ContactItem?>(null) private val _messages = mutableStateListOf<ConversationItem>() @@ -91,8 +83,10 @@ constructor( _contactItem.value = null _messages.clear() - loadContact(id) - loadMessages(id) + runOnDbThreadWithTransaction(true) { txn -> + val contact = loadContact(txn, id) + loadMessages(txn, contact) + } setNewMessage("") } @@ -125,9 +119,9 @@ constructor( m.hasText(), m.attachmentHeaders, m.autoDeleteTimer ) - txn.attach { - _messages.add(0, h.accept(conversationVisitor.value)!!) - } + val visitor = ConversationVisitor(contactItem.value!!.name, messagingManager, txn) + val msg = h.accept(visitor)!! + txn.attach { _messages.add(0, msg) } } catch (e: UnexpectedTimerException) { // todo: handle this properly LOG.warn(e) {} @@ -170,7 +164,7 @@ constructor( } } - private fun loadContact(id: ContactId) = runOnDbThreadWithTransaction(true) { txn -> + private fun loadContact(txn: Transaction, id: ContactId): ContactItem { try { val start = LogUtils.now() val contactItem = ContactItem( @@ -180,21 +174,24 @@ constructor( ) LOG.logDuration("Loading contact", start) txn.attach { _contactItem.value = contactItem } + return contactItem } catch (e: NoSuchContactException) { // todo: handle this properly LOG.warn(e) {} + throw e } } - private fun loadMessages(id: ContactId) = runOnDbThreadWithTransaction(true) { txn -> + private fun loadMessages(txn: Transaction, contact: ContactItem) { try { var start = LogUtils.now() - val headers = conversationManager.getMessageHeaders(txn, id) + val headers = conversationManager.getMessageHeaders(txn, contact.idWrapper.contactId) LOG.logDuration("Loading message headers", start) // Sort headers by timestamp in *descending* order val sorted = headers.sortedByDescending { it.timestamp } start = LogUtils.now() - val messages = sorted.map { h -> h.accept(conversationVisitor.value)!! } + val visitor = ConversationVisitor(contact.name, messagingManager, txn) + val messages = sorted.map { h -> h.accept(visitor)!! } LOG.logDuration("Loading messages", start) txn.attach { _messages.clearAndAddAll(messages) } } catch (e: NoSuchContactException) { @@ -203,15 +200,6 @@ constructor( } } - private fun loadMessageText(m: MessageId): String? { - try { - return messagingManager.getMessageText(m) // todo: use transactional API call somehow - } catch (e: DbException) { - LOG.warn(e) {} - } - return null - } - override fun eventOccurred(e: Event?) { when (e) { is ContactRemovedEvent -> { @@ -225,7 +213,11 @@ constructor( LOG.info("Message received, adding") val h = e.messageHeader // insert at start of list according to descending sort order - _messages.add(0, h.accept(conversationVisitor.value)!!) + runOnDbThreadWithTransaction(true) { txn -> + val visitor = ConversationVisitor(contactItem.value!!.name, messagingManager, txn) + val msg = h.accept(visitor)!! + txn.attach { _messages.add(0, msg) } + } } } is MessagesSentEvent -> { diff --git a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationVisitor.kt b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationVisitor.kt index f266b00cfb1ff4f0e484a60c6e9b6ae9ae487cce..d491cf6f148c81563307148fd3659a5525154233 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationVisitor.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationVisitor.kt @@ -2,6 +2,7 @@ package org.briarproject.briar.desktop.conversation import mu.KotlinLogging import org.briarproject.bramble.api.db.DatabaseExecutor +import org.briarproject.bramble.api.db.DbException import org.briarproject.bramble.api.db.Transaction import org.briarproject.bramble.api.sync.MessageId import org.briarproject.briar.api.blog.BlogInvitationRequest @@ -11,6 +12,7 @@ import org.briarproject.briar.api.forum.ForumInvitationRequest import org.briarproject.briar.api.forum.ForumInvitationResponse import org.briarproject.briar.api.introduction.IntroductionRequest import org.briarproject.briar.api.introduction.IntroductionResponse +import org.briarproject.briar.api.messaging.MessagingManager import org.briarproject.briar.api.messaging.PrivateMessageHeader import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse @@ -20,18 +22,29 @@ import org.briarproject.briar.desktop.utils.UiUtils.getContactDisplayName internal class ConversationVisitor( private val contactName: String, - private val loadMessageText: (MessageId) -> String? + private val messagingManager: MessagingManager, + private val txn: Transaction, ) : ConversationMessageVisitor<ConversationItem?> { companion object { private val LOG = KotlinLogging.logger {} } + // todo: implement some message cache similar to Briar Android + private fun loadMessageText(txn: Transaction, m: MessageId): String? { + try { + return messagingManager.getMessageText(txn, m) + } catch (e: DbException) { + LOG.warn(e) {} + } + return null + } + @DatabaseExecutor override fun visitPrivateMessageHeader(h: PrivateMessageHeader): ConversationItem { val item = ConversationMessageItem(h) if (h.hasText()) { - item.text = loadMessageText(h.id) + item.text = loadMessageText(txn, h.id) } else { LOG.warn { "private message without text" } }