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 404f42e9f5d521734de623e908cedf93e96cbb83..c531358e40ee7f857c7afd170a22205f241ace31 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationViewModel.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/conversation/ConversationViewModel.kt @@ -54,6 +54,7 @@ import org.briarproject.briar.desktop.viewmodel.SingleStateEvent import org.briarproject.briar.desktop.viewmodel.asList import org.briarproject.briar.desktop.viewmodel.asState import javax.inject.Inject +import kotlin.concurrent.thread class ConversationViewModel @Inject @@ -134,38 +135,47 @@ constructor( val contactId = _contactId.value!! // TODO: unfortunately, there is no transactional version of addLocalAttachment yet, - // so I need to create the headers outside of the transaction below. - // It' done similarly on Android: https://code.briarproject.org/briar/briar/-/blob/master/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreationTask.java#L95 - val groupId = messagingManager.getConversationId(contactId) - val headers = if (image == null) emptyList() else buildList { - val timestamp = System.currentTimeMillis() - val compressed = imageCompressor.compressImage(image!!.toAwtImage()) - add(messagingManager.addLocalAttachment(groupId, timestamp, "image/jpeg", compressed)) - } + // so I need to create the attachment headers outside of the transaction that is used to adding the + // actual message. + // It's done similarly on Android: https://code.briarproject.org/briar/briar/-/blob/master/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreationTask.java#L95 + + // Offload to a separate thread in order not to block the UI while waiting for the images to be loaded + // and added to the database. + thread { + // First: get the group id and add images if any + val groupId = messagingManager.getConversationId(contactId) + val headers = if (image == null) emptyList() else buildList { + val timestamp = System.currentTimeMillis() + val compressed = imageCompressor.compressImage(image.toAwtImage()) + add(messagingManager.addLocalAttachment(groupId, timestamp, "image/jpeg", compressed)) + } - runOnDbThreadWithTransaction(false) { txn -> - try { - val start = LogUtils.now() - val m = createMessage(txn, contactId, groupId, text, headers) - messagingManager.addLocalMessage(txn, m) - LOG.logDuration("Storing message", start) - - val message = m.message - val h = PrivateMessageHeader( - message.id, message.groupId, - message.timestamp, true, true, false, false, - m.hasText(), m.attachmentHeaders, - m.autoDeleteTimer - ) - val visitor = ConversationVisitor(contactItem.value!!.name, messagingManager, attachmentReader, txn) - val msg = h.accept(visitor)!! - txn.attach { addMessage(msg) } - } catch (e: UnexpectedTimerException) { - // todo: handle this properly - LOG.warn(e) {} - } catch (e: DbException) { - // todo: handle this properly - LOG.warn(e) {} + // Second: add the actual message to the database + runOnDbThreadWithTransaction(false) { txn -> + try { + val start = LogUtils.now() + val m = createMessage(txn, contactId, groupId!!, text, headers) + messagingManager.addLocalMessage(txn, m) + LOG.logDuration("Storing message", start) + + val message = m.message + val h = PrivateMessageHeader( + message.id, message.groupId, + message.timestamp, true, true, false, false, + m.hasText(), m.attachmentHeaders, + m.autoDeleteTimer + ) + val visitor = + ConversationVisitor(contactItem.value!!.name, messagingManager, attachmentReader, txn) + val msg = h.accept(visitor)!! + txn.attach { addMessage(msg) } + } catch (e: UnexpectedTimerException) { + // todo: handle this properly + LOG.warn(e) {} + } catch (e: DbException) { + // todo: handle this properly + LOG.warn(e) {} + } } } }