diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/sharing/BlogSharingViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/sharing/BlogSharingViewModel.kt index 9cfbc2b6f6229ad525777d52ac99b1456aca4c3d..9d9dbf201f20cd3b61bdeefc8f74bfc0eb69fb30 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/sharing/BlogSharingViewModel.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/blog/sharing/BlogSharingViewModel.kt @@ -22,6 +22,7 @@ import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.mutableStateOf import mu.KotlinLogging import org.briarproject.bramble.api.connection.ConnectionRegistry +import org.briarproject.bramble.api.contact.Contact import org.briarproject.bramble.api.contact.ContactManager import org.briarproject.bramble.api.db.Transaction import org.briarproject.bramble.api.db.TransactionManager @@ -30,12 +31,14 @@ import org.briarproject.bramble.api.event.EventBus import org.briarproject.bramble.api.lifecycle.LifecycleManager import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent +import org.briarproject.bramble.api.sync.ClientId import org.briarproject.bramble.api.sync.GroupId import org.briarproject.briar.api.blog.BlogManager import org.briarproject.briar.api.blog.BlogSharingManager import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent import org.briarproject.briar.api.conversation.ConversationManager import org.briarproject.briar.api.identity.AuthorManager +import org.briarproject.briar.api.sharing.SharingManager import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent @@ -69,6 +72,8 @@ class BlogSharingViewModel @Inject constructor( eventBus, ) { + override val clientId: ClientId = BlogSharingManager.CLIENT_ID + companion object { private val LOG = KotlinLogging.logger {} } @@ -138,6 +143,13 @@ class BlogSharingViewModel @Inject constructor( } } + override fun getSharingStatusForContact( + txn: Transaction, + groupId: GroupId, + contact: Contact, + ): SharingManager.SharingStatus = + blogSharingManager.getSharingStatus(txn, groupId, contact) + private fun loadSharingStatus(txn: Transaction, groupId: GroupId) { val map = contactManager.getContacts(txn).associate { contact -> contact.id to blogSharingManager.getSharingStatus(txn, groupId, contact) diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/sharing/ForumSharingViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/sharing/ForumSharingViewModel.kt index 773c13f4a58e66c2528653aafff1156c353df907..bca0cc4054064aa98a5372c9fb7fb2017c0b05d2 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/sharing/ForumSharingViewModel.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/sharing/ForumSharingViewModel.kt @@ -21,6 +21,7 @@ package org.briarproject.briar.desktop.forum.sharing import androidx.compose.runtime.derivedStateOf import mu.KotlinLogging import org.briarproject.bramble.api.connection.ConnectionRegistry +import org.briarproject.bramble.api.contact.Contact import org.briarproject.bramble.api.contact.ContactManager import org.briarproject.bramble.api.db.Transaction import org.briarproject.bramble.api.db.TransactionManager @@ -29,11 +30,13 @@ import org.briarproject.bramble.api.event.EventBus import org.briarproject.bramble.api.lifecycle.LifecycleManager import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent +import org.briarproject.bramble.api.sync.ClientId import org.briarproject.bramble.api.sync.GroupId import org.briarproject.briar.api.conversation.ConversationManager import org.briarproject.briar.api.forum.ForumSharingManager import org.briarproject.briar.api.forum.event.ForumInvitationResponseReceivedEvent import org.briarproject.briar.api.identity.AuthorManager +import org.briarproject.briar.api.sharing.SharingManager import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent @@ -69,10 +72,13 @@ class ForumSharingViewModel @Inject constructor( private val LOG = KotlinLogging.logger {} } + override val clientId: ClientId = ForumSharingManager.CLIENT_ID + val currentlySharedWith = derivedStateOf { _contactList.filter { _sharingStatus.value[it.id] == SHARING } } + @UiExecutor override fun reload() { _shareableSelected.value = emptySet() _sharingMessage.value = "" @@ -129,6 +135,13 @@ class ForumSharingViewModel @Inject constructor( } } + override fun getSharingStatusForContact( + txn: Transaction, + groupId: GroupId, + contact: Contact, + ): SharingManager.SharingStatus = + forumSharingManager.getSharingStatus(txn, groupId, contact) + private fun loadSharingStatus(txn: Transaction, groupId: GroupId) { val map = contactManager.getContacts(txn).associate { contact -> contact.id to forumSharingManager.getSharingStatus(txn, groupId, contact) diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/sharing/PrivateGroupSharingViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/sharing/PrivateGroupSharingViewModel.kt index 7dea7c6da11dd80db10c609309c8b366324e4d27..d56919e140f59f07d30b8ad86779b8bee61b0737 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/sharing/PrivateGroupSharingViewModel.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/sharing/PrivateGroupSharingViewModel.kt @@ -41,15 +41,18 @@ import org.briarproject.bramble.api.identity.LocalAuthor import org.briarproject.bramble.api.lifecycle.LifecycleManager import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent +import org.briarproject.bramble.api.sync.ClientId import org.briarproject.bramble.api.sync.GroupId import org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER import org.briarproject.briar.api.conversation.ConversationManager import org.briarproject.briar.api.identity.AuthorManager import org.briarproject.briar.api.privategroup.JoinMessageHeader import org.briarproject.briar.api.privategroup.PrivateGroupManager +import org.briarproject.briar.api.privategroup.event.GroupInvitationResponseReceivedEvent import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager +import org.briarproject.briar.api.sharing.SharingManager import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHAREABLE import org.briarproject.briar.api.sharing.SharingManager.SharingStatus.SHARING import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent @@ -89,6 +92,8 @@ class PrivateGroupSharingViewModel @Inject constructor( eventBus, ) { + override val clientId: ClientId = GroupInvitationManager.CLIENT_ID + private val _isCreator = mutableStateOf(false) val isCreator = _isCreator.asState() @@ -175,7 +180,6 @@ class PrivateGroupSharingViewModel @Inject constructor( val groupId = _groupId ?: return when { - // todo: is there any similar leave event we could react to? e is GroupMessageAddedEvent && e.groupId == groupId && e.header is JoinMessageHeader -> { reloadMembers() } @@ -185,6 +189,16 @@ class PrivateGroupSharingViewModel @Inject constructor( reloadMembers() } + e is GroupInvitationResponseReceivedEvent && e.messageHeader.shareableId == groupId -> { + if (e.messageHeader.wasAccepted()) { + _sharingStatus.value += e.contactId to SHARING + val connected = connectionRegistry.isConnected(e.contactId) + _sharingInfo.update { addContact(connected) } + } else { + _sharingStatus.value += e.contactId to SHAREABLE + } + } + // todo: update member list on contact alias/avatar changed (may be member) // todo: any way of coupling member list to contact list for members that are actually contacts? @@ -212,6 +226,13 @@ class PrivateGroupSharingViewModel @Inject constructor( } } + override fun getSharingStatusForContact( + txn: Transaction, + groupId: GroupId, + contact: Contact, + ): SharingManager.SharingStatus = + privateGroupInvitationManager.getSharingStatus(txn, contact, groupId) + private fun loadSharingStatus( txn: Transaction, groupId: GroupId, diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/sharing/ThreadedGroupSharingViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/sharing/ThreadedGroupSharingViewModel.kt index 55779093e0ca81c50bc6514d12d18cc21f90656a..aea3e2eab2b01705506f94a8a8724265eb2a18ca 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/sharing/ThreadedGroupSharingViewModel.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/sharing/ThreadedGroupSharingViewModel.kt @@ -20,13 +20,20 @@ package org.briarproject.briar.desktop.threadedgroup.sharing import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.mutableStateOf +import mu.KotlinLogging import org.briarproject.bramble.api.connection.ConnectionRegistry +import org.briarproject.bramble.api.contact.Contact import org.briarproject.bramble.api.contact.ContactId import org.briarproject.bramble.api.contact.ContactManager +import org.briarproject.bramble.api.contact.event.ContactAddedEvent +import org.briarproject.bramble.api.db.Transaction import org.briarproject.bramble.api.db.TransactionManager +import org.briarproject.bramble.api.event.Event import org.briarproject.bramble.api.event.EventBus import org.briarproject.bramble.api.lifecycle.LifecycleManager +import org.briarproject.bramble.api.sync.ClientId import org.briarproject.bramble.api.sync.GroupId +import org.briarproject.bramble.api.versioning.event.ClientVersionUpdatedEvent import org.briarproject.briar.api.conversation.ConversationManager import org.briarproject.briar.api.identity.AuthorManager import org.briarproject.briar.api.sharing.SharingConstants @@ -58,6 +65,12 @@ abstract class ThreadedGroupSharingViewModel( db, eventBus, ) { + companion object { + private val LOG = KotlinLogging.logger {} + } + + protected abstract val clientId: ClientId + protected var _groupId: GroupId? = null protected val _sharingInfo = mutableStateOf(SharingInfo(0, 0)) @@ -67,8 +80,6 @@ abstract class ThreadedGroupSharingViewModel( protected val _shareableSelected = mutableStateOf(emptySet<ContactId>()) protected val _sharingMessage = mutableStateOf("") - open val deleteDialogCondition = false - data class ShareableContactItem(val status: SharingManager.SharingStatus, val contactItem: ContactItem) val contactList = derivedStateOf { @@ -95,6 +106,19 @@ abstract class ThreadedGroupSharingViewModel( loadContacts() } + override fun eventOccurred(e: Event) { + super.eventOccurred(e) + when { + e is ContactAddedEvent -> { + _groupId?.let { loadSharingStatusForContact(it, e.contactId) } + } + + e is ClientVersionUpdatedEvent && e.clientVersion.clientId == clientId -> { + _groupId?.let { loadSharingStatusForContact(it, e.contactId) } + } + } + } + @UiExecutor fun setGroupId(groupId: GroupId) { if (_groupId == groupId) return @@ -104,6 +128,21 @@ abstract class ThreadedGroupSharingViewModel( protected abstract fun reload() + private fun loadSharingStatusForContact(groupId: GroupId, contactId: ContactId) = + runOnDbThreadWithTransaction(true) { txn -> + val contact = contactManager.getContact(txn, contactId) + val status = getSharingStatusForContact(txn, groupId, contact) + txn.attach { + _sharingStatus.value += contactId to status + } + } + + protected abstract fun getSharingStatusForContact( + txn: Transaction, + groupId: GroupId, + contact: Contact, + ): SharingManager.SharingStatus + data class SharingInfo(val total: Int, val online: Int) { fun addContact(connected: Boolean) = copy( total = total + 1,