From fa17b3c702f19b380616331636e4d78b49e65589 Mon Sep 17 00:00:00 2001 From: ialokim <ialokim@mailbox.org> Date: Tue, 30 May 2023 23:34:50 +0200 Subject: [PATCH] add option to mark entire group conversation as read --- .../briar/desktop/forum/ForumScreen.kt | 4 ++-- .../ForumConversationViewModel.kt | 4 ++-- .../forum/conversation/ForumDropdownMenu.kt | 12 ++++++++++ .../forum/sharing/ForumSharingViewModel.kt | 2 +- .../privategroup/PrivateGroupScreen.kt | 3 ++- .../PrivateGroupConversationViewModel.kt | 4 ++-- .../conversation/PrivateGroupDropdownMenu.kt | 12 ++++++++++ .../ThreadedConversationViewModel.kt | 22 +++++++++---------- .../ThreadedGroupConversationScreen.kt | 5 ++++- .../conversation/ThreadedGroupDropdownMenu.kt | 1 + .../resources/strings/BriarDesktop.properties | 1 + 11 files changed, 50 insertions(+), 20 deletions(-) diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/ForumScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/ForumScreen.kt index ec14f6f623..3eaa778c33 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/ForumScreen.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/ForumScreen.kt @@ -30,8 +30,8 @@ fun ForumScreen( ) = ThreadedGroupScreen( strings = ForumStrings, viewModel = viewModel, - dropdownMenu = { sharingViewModel, expanded, onClose, onLeaveForumClick -> + dropdownMenu = { sharingViewModel, expanded, onClose, onMarkReadClick, onLeaveForumClick -> val forumSharingViewModel = sharingViewModel as ForumSharingViewModel - ForumDropdownMenu(forumSharingViewModel, expanded, onClose, onLeaveForumClick) + ForumDropdownMenu(forumSharingViewModel, expanded, onClose, onMarkReadClick, onLeaveForumClick) } ) diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/conversation/ForumConversationViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/conversation/ForumConversationViewModel.kt index 4d7e26cf4f..429db62a02 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/conversation/ForumConversationViewModel.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/conversation/ForumConversationViewModel.kt @@ -112,8 +112,8 @@ class ForumConversationViewModel @Inject constructor( } @DatabaseExecutor - override fun markThreadItemRead(groupId: GroupId, id: MessageId) = - forumManager.setReadFlag(groupId, id, true) + override fun markThreadItemRead(txn: Transaction, groupId: GroupId, id: MessageId) = + forumManager.setReadFlag(txn, groupId, id, true) @UiExecutor override fun deleteGroup() { diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/conversation/ForumDropdownMenu.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/conversation/ForumDropdownMenu.kt index 871d3b4b03..19b06b6ddf 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/conversation/ForumDropdownMenu.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forum/conversation/ForumDropdownMenu.kt @@ -35,6 +35,7 @@ fun ForumDropdownMenu( forumSharingViewModel: ForumSharingViewModel, expanded: Boolean, onClose: () -> Unit, + onMarkReadClick: () -> Unit, onLeaveForumClick: () -> Unit, ) = DropdownMenu( expanded = expanded, @@ -74,6 +75,17 @@ fun ForumDropdownMenu( style = MaterialTheme.typography.body2, ) } + DropdownMenuItem( + onClick = { + onClose() + onMarkReadClick() + } + ) { + Text( + i18n("group.mark.read"), + style = MaterialTheme.typography.body2, + ) + } DropdownMenuItem( onClick = { onClose() 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 d47f5e7b7c..773c13f4a5 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 @@ -129,7 +129,7 @@ class ForumSharingViewModel @Inject constructor( } } - fun loadSharingStatus(txn: Transaction, groupId: GroupId) { + 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/PrivateGroupScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/PrivateGroupScreen.kt index 48d13acb0b..9a94982bce 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/PrivateGroupScreen.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/PrivateGroupScreen.kt @@ -43,12 +43,13 @@ fun PrivateGroupScreen( ThreadedGroupScreen( strings = PrivateGroupStrings, viewModel = viewModel, - dropdownMenu = { sharingViewModel, expanded, onClose, onLeaveOrDissolvePrivateGroupClick -> + dropdownMenu = { sharingViewModel, expanded, onClose, onMarkReadClick, onLeaveOrDissolvePrivateGroupClick -> val privateGroupSharingViewModel = sharingViewModel as PrivateGroupSharingViewModel PrivateGroupDropdownMenu( privateGroupSharingViewModel = privateGroupSharingViewModel, expanded = expanded, onClose = onClose, + onMarkReadClick = onMarkReadClick, onLeaveOrDissolvePrivateGroupClick = onLeaveOrDissolvePrivateGroupClick ) }, diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/conversation/PrivateGroupConversationViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/conversation/PrivateGroupConversationViewModel.kt index 81695874c4..ab44963e73 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/conversation/PrivateGroupConversationViewModel.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/conversation/PrivateGroupConversationViewModel.kt @@ -135,8 +135,8 @@ class PrivateGroupConversationViewModel @Inject constructor( } @DatabaseExecutor - override fun markThreadItemRead(groupId: GroupId, id: MessageId) = - privateGroupManager.setReadFlag(groupId, id, true) + override fun markThreadItemRead(txn: Transaction, groupId: GroupId, id: MessageId) = + privateGroupManager.setReadFlag(txn, groupId, id, true) @UiExecutor override fun deleteGroup() { diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/conversation/PrivateGroupDropdownMenu.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/conversation/PrivateGroupDropdownMenu.kt index a23d807ab2..efb37e4216 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/conversation/PrivateGroupDropdownMenu.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroup/conversation/PrivateGroupDropdownMenu.kt @@ -35,6 +35,7 @@ fun PrivateGroupDropdownMenu( privateGroupSharingViewModel: PrivateGroupSharingViewModel, expanded: Boolean, onClose: () -> Unit, + onMarkReadClick: () -> Unit, onLeaveOrDissolvePrivateGroupClick: () -> Unit, ) = DropdownMenu( expanded = expanded, @@ -76,6 +77,17 @@ fun PrivateGroupDropdownMenu( ) } } + DropdownMenuItem( + onClick = { + onClose() + onMarkReadClick() + } + ) { + Text( + i18n("group.mark.read"), + style = MaterialTheme.typography.body2, + ) + } DropdownMenuItem( onClick = { onClose() diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedConversationViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedConversationViewModel.kt index 4d8fe22105..8190c5fd61 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedConversationViewModel.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedConversationViewModel.kt @@ -112,13 +112,13 @@ abstract class ThreadedConversationViewModel( } @DatabaseExecutor - abstract fun markThreadItemRead(groupId: GroupId, id: MessageId) + abstract fun markThreadItemRead(txn: Transaction, groupId: GroupId, id: MessageId) @UiExecutor - fun markThreadItemsRead(ids: List<MessageId>) { + fun markThreadItemsRead(ids: List<MessageId>? = null) { // TODO messageTree.get(id) would be nice, but not in briar-core val readIds = (state.value as? Loaded)?.posts?.filter { item -> - !item.isRead && ids.contains(item.id) + ids?.contains(item.id) ?: true && !item.isRead }?.map { item -> item.isRead = true item.id @@ -126,17 +126,17 @@ abstract class ThreadedConversationViewModel( val groupId = _threadedGroupItem.value?.id if (readIds.isNotEmpty() && groupId != null) { - runOnDbThread { + runOnDbThreadWithTransaction(false) { txn -> readIds.forEach { id -> - markThreadItemRead(groupId, id) + markThreadItemRead(txn, groupId, id) + } + txn.attach(ThreadedGroupMessageReadEvent(clientId, groupId, readIds.size)) + txn.attach { + // TODO replace immutable ThreadItems instead to avoid recomposing whole list + val messageTree = (state.value as? Loaded)?.messageTree ?: return@attach + _state.value = Loaded(messageTree) } } - // we don't attach this to the transaction that actually changes the DB, - // but that should be fine for this purpose of just decrementing a counter - eventBus.broadcast(ThreadedGroupMessageReadEvent(clientId, groupId, readIds.size)) - // TODO replace immutable ThreadItems instead to avoid recomposing whole list - val messageTree = (state.value as? Loaded)?.messageTree ?: return - _state.value = Loaded(messageTree) } } diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedGroupConversationScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedGroupConversationScreen.kt index 2aebe4f82d..86b607c30a 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedGroupConversationScreen.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedGroupConversationScreen.kt @@ -76,6 +76,7 @@ fun ThreadedGroupConversationScreen( threadedGroupItem = groupItem, sharingViewModel = viewModel.sharingViewModel, onGroupDelete = viewModel::deleteGroup, + onMarkRead = viewModel::markThreadItemsRead, dropdownMenu = dropdownMenu, ) } @@ -108,6 +109,7 @@ private fun ThreadedGroupConversationHeader( strings: ThreadedGroupStrings, threadedGroupItem: ThreadedGroupItem, sharingViewModel: ThreadedGroupSharingViewModel, + onMarkRead: () -> Unit, onGroupDelete: () -> Unit, dropdownMenu: ThreadedGroupDropdownMenu, ) { @@ -151,7 +153,8 @@ private fun ThreadedGroupConversationHeader( dropdownMenu( sharingViewModel, menuState.value == MAIN, - close + close, + onMarkRead, ) { deleteGroupDialogVisible.value = true } } } diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedGroupDropdownMenu.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedGroupDropdownMenu.kt index dc6909d950..b9cd057015 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedGroupDropdownMenu.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/threadedgroup/conversation/ThreadedGroupDropdownMenu.kt @@ -25,5 +25,6 @@ typealias ThreadedGroupDropdownMenu = @Composable ( sharingViewModel: ThreadedGroupSharingViewModel, expanded: Boolean, onClose: () -> Unit, + onMarkReadClick: () -> Unit, onLeaveGroupClick: () -> Unit, ) -> Unit diff --git a/briar-desktop/src/main/resources/strings/BriarDesktop.properties b/briar-desktop/src/main/resources/strings/BriarDesktop.properties index 327cf981bb..afa4b54bbd 100644 --- a/briar-desktop/src/main/resources/strings/BriarDesktop.properties +++ b/briar-desktop/src/main/resources/strings/BriarDesktop.properties @@ -209,6 +209,7 @@ group.member.created_you=You created the group group.member.created_contact={0} created the group group.invite.action.title=Invite Contacts group.invite.action.no_contacts=No contacts yet. You can only invite contacts to your private group. +group.mark.read=Mark as read # Introduction introduction.introduce=Make Introduction -- GitLab