diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/AddForumDialog.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/AddForumDialog.kt index 529e80f028af236e5efd9cd133c19a7693c075ac..d3d9a0c373dbedd8bd0b75eedc82d7e6d8422713 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/AddForumDialog.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/AddForumDialog.kt @@ -35,7 +35,6 @@ import androidx.compose.material.TextButton import androidx.compose.material.rememberScaffoldState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable @@ -56,16 +55,16 @@ import java.awt.Dimension fun main() = preview { val visible = mutableStateOf(true) - AddForumDialog(visible, {}, { visible.value = false }) + AddForumDialog(visible.value, {}, { visible.value = false }) } @Composable fun AddForumDialog( - visible: State<Boolean>, + visible: Boolean, onCreate: (String) -> Unit, onCancelButtonClicked: () -> Unit, ) { - if (!visible.value) return + if (!visible) return Dialog( title = i18n("forum.add.title"), onCloseRequest = onCancelButtonClicked, diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumScreen.kt index 91ce4ac692c7b7e7abddf20f79cb38e74f012d80..11754834928551376dfb16d12dfdba3769b692cd 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumScreen.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumScreen.kt @@ -41,7 +41,7 @@ fun ForumScreen( ) { val addDialogVisible = remember { mutableStateOf(false) } AddForumDialog( - visible = addDialogVisible, + visible = addDialogVisible.value, onCreate = { name -> viewModel.createForum(name) addDialogVisible.value = false @@ -54,9 +54,9 @@ fun ForumScreen( } else { Row(modifier = Modifier.fillMaxWidth()) { GroupListComposable( - list = viewModel.forumList, + list = viewModel.forumList.value, isSelected = viewModel::isSelected, - filterBy = viewModel.filterBy, + filterBy = viewModel.filterBy.value, onFilterSet = viewModel::setFilterBy, onGroupItemSelected = viewModel::selectGroup, onAddButtonClicked = { addDialogVisible.value = true }, diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumViewModel.kt index 5b3e28d0833350cf018c3103d346acf053a84f6e..9b05d6db6c3a5fa993418985a3c86c5903c5b841 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumViewModel.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumViewModel.kt @@ -21,48 +21,22 @@ package org.briarproject.briar.desktop.forums import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import org.briarproject.bramble.api.crypto.CryptoExecutor 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.identity.IdentityManager -import org.briarproject.bramble.api.identity.LocalAuthor import org.briarproject.bramble.api.lifecycle.LifecycleManager import org.briarproject.bramble.api.sync.GroupId -import org.briarproject.bramble.api.sync.MessageId import org.briarproject.bramble.api.sync.event.GroupAddedEvent import org.briarproject.bramble.api.sync.event.GroupRemovedEvent -import org.briarproject.bramble.api.system.Clock -import org.briarproject.briar.api.client.MessageTracker.GroupCount import org.briarproject.briar.api.forum.ForumManager -import org.briarproject.briar.client.MessageTreeImpl import org.briarproject.briar.desktop.threading.BriarExecutors -import org.briarproject.briar.desktop.threading.UiExecutor import org.briarproject.briar.desktop.utils.clearAndAddAll import org.briarproject.briar.desktop.viewmodel.EventListenerDbViewModel import org.briarproject.briar.desktop.viewmodel.asState -import java.lang.Long.max import javax.inject.Inject -sealed class PostsState -object Loading : PostsState() -class Loaded( - val messageTree: MessageTreeImpl<ThreadItem>, - val scrollTo: MessageId? = null, -) : PostsState() { - val posts: MutableList<ThreadItem> get() = messageTree.depthFirstOrder() -} - class ForumViewModel @Inject constructor( private val forumManager: ForumManager, - private val identityManager: IdentityManager, - private val clock: Clock, - @CryptoExecutor private val cryptoDispatcher: CoroutineDispatcher, briarExecutors: BriarExecutors, lifecycleManager: LifecycleManager, db: TransactionManager, @@ -85,9 +59,6 @@ class ForumViewModel @Inject constructor( private val _filterBy = mutableStateOf("") val filterBy = _filterBy.asState() - private val _posts = mutableStateOf<PostsState>(Loading) - val posts = _posts.asState() - override fun onInit() { super.onInit() loadGroups() @@ -124,59 +95,11 @@ class ForumViewModel @Inject constructor( fun selectGroup(groupItem: GroupItem) { _selectedGroupItem.value = groupItem - loadPosts(groupItem.id) } fun isSelected(groupId: GroupId) = _selectedGroupItem.value?.id == groupId - private fun loadPosts(groupId: GroupId) { - _posts.value = Loading - runOnDbThreadWithTransaction(true) { txn -> - val items = forumManager.getPostHeaders(txn, groupId).map { header -> - ForumPostItem(header, forumManager.getPostText(txn, header.id)) - } - val tree = MessageTreeImpl<ThreadItem>().apply { add(items) } - txn.attach { - _posts.value = Loaded(tree) - } - } - } - fun setFilterBy(filter: String) { _filterBy.value = filter } - - @OptIn(DelicateCoroutinesApi::class) - fun createPost(groupItem: GroupItem, text: String, parentId: MessageId?) = GlobalScope.launch { - val author = runOnDbThreadWithTransaction<LocalAuthor>(false) { txn -> - identityManager.getLocalAuthor(txn) - } - val count = runOnDbThreadWithTransaction<GroupCount>(false) { txn -> - forumManager.getGroupCount(txn, groupItem.id) - } - val timestamp = max(count.latestMsgTime + 1, clock.currentTimeMillis()) - val post = withContext(cryptoDispatcher) { - forumManager.createLocalPost(groupItem.id, text, timestamp, parentId, author) - } - runOnDbThreadWithTransaction(false) { txn -> - val header = forumManager.addLocalPost(txn, post) - txn.attach { - val item = ForumPostItem(header, text) - addItem(item, item.id) - } - } - } - - @UiExecutor - private fun addItem(item: ForumPostItem, scrollTo: MessageId? = null) { - // If items haven't loaded, we need to wait until they have. - // Since this was a R/W DB transaction, the load will pick up this item. - val tree = (posts.value as? Loaded)?.messageTree ?: return - tree.add(item) - _posts.value = Loaded(tree, scrollTo) - } - - fun deleteGroup(groupItem: GroupItem) { - forumManager.removeForum((groupItem as ForumItem).forum) - } } diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupConversationScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupConversationScreen.kt index 6540ceec2f0998784cc40f562a68a5620379fcd9..1eb22c902051067fd90df8c7943bfa6934aaaa14 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupConversationScreen.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupConversationScreen.kt @@ -41,6 +41,7 @@ import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MoreVert import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment.Companion.BottomCenter @@ -49,7 +50,6 @@ import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextOverflow.Companion.Ellipsis import androidx.compose.ui.unit.dp -import org.briarproject.bramble.api.sync.MessageId import org.briarproject.briar.desktop.contact.ContactDropDown.State.CLOSED import org.briarproject.briar.desktop.contact.ContactDropDown.State.MAIN import org.briarproject.briar.desktop.ui.Constants.HEADER_SIZE @@ -60,9 +60,11 @@ import org.briarproject.briar.desktop.viewmodel.viewModel @Composable fun GroupConversationScreen( groupItem: GroupItem, - viewModel: ForumViewModel = viewModel(), + viewModel: ThreadedConversationViewModel = viewModel(), ) { - val selectedPost = remember { mutableStateOf<MessageId?>(null) } + LaunchedEffect(groupItem) { + viewModel.setGroupItem(groupItem) + } Scaffold( topBar = { GroupConversationHeader(groupItem) { viewModel.deleteGroup(groupItem) } @@ -70,13 +72,14 @@ fun GroupConversationScreen( content = { padding -> ThreadedConversationScreen( postsState = viewModel.posts.value, - selectedPost = selectedPost, + selectedPost = viewModel.selectedPost.value, + onPostSelected = viewModel::selectPost, modifier = Modifier.padding(padding) ) }, bottomBar = { - GroupInputComposable(selectedPost) { text -> - viewModel.createPost(groupItem, text, selectedPost.value) + GroupInputComposable(viewModel.selectedPost.value) { text -> + viewModel.createPost(groupItem, text, viewModel.selectedPost.value?.id) } } ) diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupInputComposable.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupInputComposable.kt index 1b1b7120e949613b14de6922a9b1db78546baec6..1543d36ce979685a9bb2a02cf206f3e3ead42b38 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupInputComposable.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupInputComposable.kt @@ -32,7 +32,6 @@ import androidx.compose.material.TextFieldExt.moveFocusOnTab import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Send import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.ExperimentalComposeUiApi @@ -40,7 +39,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.pointer.PointerIconDefaults import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.unit.dp -import org.briarproject.bramble.api.sync.MessageId import org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_TEXT_LENGTH import org.briarproject.briar.desktop.theme.sendButton import org.briarproject.briar.desktop.ui.HorizontalDivider @@ -49,7 +47,7 @@ import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n @Composable @OptIn(ExperimentalComposeUiApi::class) fun GroupInputComposable( - selectedPost: State<MessageId?>, + selectedPost: ThreadItem?, onSend: (String) -> Unit, ) { val postText = rememberSaveable { mutableStateOf("") } @@ -70,7 +68,7 @@ fun GroupInputComposable( textStyle = MaterialTheme.typography.body1, placeholder = { Text( - text = if (selectedPost.value == null) { + text = if (selectedPost == null) { i18n("forum.message.hint") } else { i18n("forum.message.reply.hint") diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupListComposable.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupListComposable.kt index 7ced0abe86fdff5e0996e1ba559ed226b21d7f73..0c08e2a6d5cb208c064bb2ee6909c6dac4fef5aa 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupListComposable.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/GroupListComposable.kt @@ -36,7 +36,6 @@ import androidx.compose.material.Surface import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.AddComment import androidx.compose.runtime.Composable -import androidx.compose.runtime.State import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.contentDescription @@ -52,9 +51,9 @@ import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n @Composable fun GroupListComposable( - list: State<List<GroupItem>>, + list: List<GroupItem>, isSelected: (GroupId) -> Boolean, - filterBy: State<String>, + filterBy: String, onFilterSet: (String) -> Unit, onGroupItemSelected: (GroupItem) -> Unit, onAddButtonClicked: () -> Unit, @@ -71,7 +70,7 @@ fun GroupListComposable( SearchTextField( placeholder = i18n("forum.search.title"), icon = Icons.Filled.AddComment, - searchValue = filterBy.value, + searchValue = filterBy, addButtonDescription = i18n("forum.add.title"), onValueChange = onFilterSet, onAddButtonClicked = onAddButtonClicked, @@ -85,7 +84,7 @@ fun GroupListComposable( contentDescription = i18n("access.forums.list") }.selectableGroup() ) { - items(list.value) { item -> + items(list) { item -> GroupCard( item = item, onGroupItemSelected = onGroupItemSelected, diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadedConversationScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadedConversationScreen.kt index 679c9492f83d6f47d3126fc493ab144ae82e4a08..7f899a9e7d5a9b44cd3c9867af07f98264ab973b 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadedConversationScreen.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadedConversationScreen.kt @@ -34,13 +34,11 @@ import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment.Companion.CenterEnd import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch -import org.briarproject.bramble.api.sync.MessageId import org.briarproject.briar.desktop.forums.ThreadItem.Companion.UNDEFINED import org.briarproject.briar.desktop.theme.selectedCard import org.briarproject.briar.desktop.theme.surfaceVariant @@ -50,8 +48,9 @@ import org.briarproject.briar.desktop.ui.Loader @Composable fun ThreadedConversationScreen( postsState: PostsState, - selectedPost: MutableState<MessageId?>, - modifier: Modifier = Modifier + selectedPost: ThreadItem?, + onPostSelected: (ThreadItem) -> Unit, + modifier: Modifier = Modifier, ) = when (postsState) { Loading -> Loader() is Loaded -> { @@ -68,7 +67,7 @@ fun ThreadedConversationScreen( modifier = Modifier.selectableGroup() ) { items(postsState.posts) { item -> - ThreadItemComposable(item, selectedPost) + ThreadItemComposable(item, selectedPost, onPostSelected) HorizontalDivider() } } @@ -81,8 +80,12 @@ fun ThreadedConversationScreen( } @Composable -fun ThreadItemComposable(item: ThreadItem, selectedPost: MutableState<MessageId?>) { - val isSelected = selectedPost.value == item.id +fun ThreadItemComposable( + item: ThreadItem, + selectedPost: ThreadItem?, + onPostSelected: (ThreadItem) -> Unit, +) { + val isSelected = selectedPost == item Text( text = item.text, modifier = Modifier @@ -95,7 +98,7 @@ fun ThreadItemComposable(item: ThreadItem, selectedPost: MutableState<MessageId? } ).selectable( selected = isSelected, - onClick = { selectedPost.value = item.id } + onClick = { onPostSelected(item) } ) .padding(4.dp) .padding( diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadedConversationViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadedConversationViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..bea6fc19a3b9cb9c14b23952b519684b333b8cc6 --- /dev/null +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ThreadedConversationViewModel.kt @@ -0,0 +1,141 @@ +/* + * Briar Desktop + * Copyright (C) 2021-2022 The Briar Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package org.briarproject.briar.desktop.forums + +import androidx.compose.runtime.mutableStateOf +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.briarproject.bramble.api.crypto.CryptoExecutor +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.identity.IdentityManager +import org.briarproject.bramble.api.identity.LocalAuthor +import org.briarproject.bramble.api.lifecycle.LifecycleManager +import org.briarproject.bramble.api.sync.GroupId +import org.briarproject.bramble.api.sync.MessageId +import org.briarproject.bramble.api.system.Clock +import org.briarproject.briar.api.client.MessageTracker +import org.briarproject.briar.api.forum.ForumManager +import org.briarproject.briar.client.MessageTreeImpl +import org.briarproject.briar.desktop.threading.BriarExecutors +import org.briarproject.briar.desktop.threading.UiExecutor +import org.briarproject.briar.desktop.viewmodel.EventListenerDbViewModel +import org.briarproject.briar.desktop.viewmodel.asState +import org.slf4j.LoggerFactory.getLogger +import java.lang.Long.max +import javax.inject.Inject + +sealed class PostsState +object Loading : PostsState() +class Loaded( + val messageTree: MessageTreeImpl<ThreadItem>, + val scrollTo: MessageId? = null, +) : PostsState() { + val posts: MutableList<ThreadItem> get() = messageTree.depthFirstOrder() +} + +class ThreadedConversationViewModel @Inject constructor( + private val forumManager: ForumManager, + private val identityManager: IdentityManager, + private val clock: Clock, + @CryptoExecutor private val cryptoDispatcher: CoroutineDispatcher, + briarExecutors: BriarExecutors, + lifecycleManager: LifecycleManager, + db: TransactionManager, + eventBus: EventBus, +) : EventListenerDbViewModel(briarExecutors, lifecycleManager, db, eventBus) { + + companion object { + private val LOG = getLogger(ThreadedConversationViewModel::class.java) + } + + private lateinit var groupItem: GroupItem + + private val _posts = mutableStateOf<PostsState>(Loading) + val posts = _posts.asState() + + private val _selectedPost = mutableStateOf<ThreadItem?>(null) + val selectedPost = _selectedPost.asState() + + @UiExecutor + fun setGroupItem(groupItem: GroupItem) { + this.groupItem = groupItem + loadPosts(groupItem.id) + } + + override fun eventOccurred(e: Event) { + } + + private fun loadPosts(groupId: GroupId) { + _posts.value = Loading + runOnDbThreadWithTransaction(true) { txn -> + val items = forumManager.getPostHeaders(txn, groupId).map { header -> + ForumPostItem(header, forumManager.getPostText(txn, header.id)) + } + val tree = MessageTreeImpl<ThreadItem>().apply { add(items) } + txn.attach { + _posts.value = Loaded(tree) + } + } + } + + @UiExecutor + fun selectPost(post: ThreadItem?) { + _selectedPost.value = post + } + + @UiExecutor + @OptIn(DelicateCoroutinesApi::class) + fun createPost(groupItem: GroupItem, text: String, parentId: MessageId?) = GlobalScope.launch { + val author = runOnDbThreadWithTransaction<LocalAuthor>(false) { txn -> + identityManager.getLocalAuthor(txn) + } + val count = runOnDbThreadWithTransaction<MessageTracker.GroupCount>(false) { txn -> + forumManager.getGroupCount(txn, groupItem.id) + } + val timestamp = max(count.latestMsgTime + 1, clock.currentTimeMillis()) + val post = withContext(cryptoDispatcher) { + forumManager.createLocalPost(groupItem.id, text, timestamp, parentId, author) + } + runOnDbThreadWithTransaction(false) { txn -> + val header = forumManager.addLocalPost(txn, post) + txn.attach { + val item = ForumPostItem(header, text) + addItem(item, item.id) + } + } + } + + @UiExecutor + private fun addItem(item: ForumPostItem, scrollTo: MessageId? = null) { + // If items haven't loaded, we need to wait until they have. + // Since this was a R/W DB transaction, the load will pick up this item. + val tree = (posts.value as? Loaded)?.messageTree ?: return + tree.add(item) + _posts.value = Loaded(tree, scrollTo) + } + + fun deleteGroup(groupItem: GroupItem) { + forumManager.removeForum((groupItem as ForumItem).forum) + } +} diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroups/ThreadedConversationScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroups/ThreadedConversationScreen.kt index f5cad0ee065cb005f0af24fce2fd7fab158f642a..3708d9ad8e52c39440f2f6148b9b8a68fbeaa430 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroups/ThreadedConversationScreen.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/privategroups/ThreadedConversationScreen.kt @@ -21,10 +21,8 @@ package org.briarproject.briar.desktop.privategroups import androidx.compose.runtime.Composable import org.briarproject.bramble.api.sync.GroupId import org.briarproject.briar.desktop.ui.UiPlaceholder -import org.briarproject.briar.desktop.viewmodel.viewModel @Composable fun ThreadedConversationScreen( groupId: GroupId, - viewModel: ThreadedConversationViewModel = viewModel(), ) = UiPlaceholder() diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/ViewModelModule.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/ViewModelModule.kt index bcb43539967d35b874c42033ecf5b643927ed529..45797f9d8fa321854e7ce730e39788cccdf0dc85 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/ViewModelModule.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/viewmodel/ViewModelModule.kt @@ -26,11 +26,11 @@ import org.briarproject.briar.desktop.contact.ContactListViewModel import org.briarproject.briar.desktop.contact.add.remote.AddContactViewModel import org.briarproject.briar.desktop.conversation.ConversationViewModel import org.briarproject.briar.desktop.forums.ForumViewModel +import org.briarproject.briar.desktop.forums.ThreadedConversationViewModel import org.briarproject.briar.desktop.introduction.IntroductionViewModel import org.briarproject.briar.desktop.login.StartupViewModel import org.briarproject.briar.desktop.navigation.SidebarViewModel import org.briarproject.briar.desktop.privategroups.PrivateGroupListViewModel -import org.briarproject.briar.desktop.privategroups.ThreadedConversationViewModel import org.briarproject.briar.desktop.settings.SettingsViewModel import kotlin.reflect.KClass