From 565bcfec9c018fa91b64ed295a1ebcaae070fbf8 Mon Sep 17 00:00:00 2001 From: ialokim <ialokim@mailbox.org> Date: Sat, 30 Oct 2021 00:17:15 +0200 Subject: [PATCH] unify filter approach in view models, fix selection of contacts after filtering the list --- .../briar/desktop/contact/ContactList.kt | 10 ++-- .../desktop/contact/ContactListViewModel.kt | 51 +++++-------------- .../desktop/contact/ContactsViewModel.kt | 25 ++++++--- .../conversation/PrivateMessageView.kt | 2 +- .../introduction/IntroductionViewModel.kt | 5 +- .../briarproject/briar/desktop/ui/BriarUi.kt | 1 - 6 files changed, 43 insertions(+), 51 deletions(-) diff --git a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt index 4e769de56a..7fa969a5b3 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt @@ -6,7 +6,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.items import androidx.compose.material.MaterialTheme import androidx.compose.material.Scaffold import androidx.compose.runtime.Composable @@ -45,8 +45,12 @@ fun ContactList( }, content = { LazyColumn { - itemsIndexed(viewModel.contactList) { index, contactItem -> - ContactCard(contactItem, { viewModel.selectContact(index) }, viewModel.isSelected(index)) + items(viewModel.contactList) { contactItem -> + ContactCard( + contactItem, + { viewModel.selectContact(contactItem.contact) }, + viewModel.isSelected(contactItem.contact) + ) } } }, diff --git a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactListViewModel.kt b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactListViewModel.kt index ef763a604c..ee4a7f8c82 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactListViewModel.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactListViewModel.kt @@ -1,10 +1,9 @@ package org.briarproject.briar.desktop.contact import androidx.compose.runtime.State -import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import org.briarproject.bramble.api.connection.ConnectionRegistry -import org.briarproject.bramble.api.contact.ContactId +import org.briarproject.bramble.api.contact.Contact import org.briarproject.bramble.api.contact.ContactManager import org.briarproject.bramble.api.contact.event.ContactAliasChangedEvent import org.briarproject.bramble.api.event.Event @@ -32,44 +31,32 @@ constructor( eventBus.addListener(this) } - private val _filteredContactList = mutableStateListOf<ContactItem>() private val _filterBy = mutableStateOf("") - private var _selectedContactIndex = -1 - private val _selectedContact = mutableStateOf<ContactItem?>(null) + private val _selectedContact = mutableStateOf<Contact?>(null) - override val contactList: List<ContactItem> = _filteredContactList val filterBy: State<String> = _filterBy - val selectedContact: State<ContactItem?> = _selectedContact + val selectedContact: State<Contact?> = _selectedContact - override fun loadContacts() { - super.loadContacts() - updateFilteredList() + fun selectContact(contact: Contact) { + _selectedContact.value = contact } - fun selectContact(index: Int) { - _selectedContactIndex = index - _selectedContact.value = _filteredContactList[index] - } + fun isSelected(contact: Contact) = _selectedContact.value?.id == contact.id - fun isSelected(index: Int) = _selectedContactIndex == index - - private fun updateFilteredList() { - _filteredContactList.apply { - clear() - addAll( - _contactList.filter { - // todo: also filter on alias? - it.contact.author.name.lowercase().contains(_filterBy.value) - } - ) - } - } + override fun filterContact(contact: Contact) = + // todo: also filter on alias + contact.author.name.contains(_filterBy.value, ignoreCase = true) fun setFilterBy(filter: String) { _filterBy.value = filter updateFilteredList() } + override fun updateFilteredList() { + super.updateFilteredList() + _selectedContact.value?.let { if (!filterContact(it)) _selectedContact.value = null } + } + override fun eventOccurred(e: Event?) { super.eventOccurred(e) when (e) { @@ -83,14 +70,4 @@ constructor( } } } - - override fun updateItem(contactId: ContactId, update: (ContactItem) -> ContactItem) { - super.updateItem(contactId, update) - updateFilteredList() - } - - override fun removeItem(contactId: ContactId) { - super.removeItem(contactId) - updateFilteredList() - } } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactsViewModel.kt b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactsViewModel.kt index ffd994358e..ccb10ccd33 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactsViewModel.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactsViewModel.kt @@ -1,5 +1,6 @@ package org.briarproject.briar.desktop.contact +import androidx.compose.runtime.mutableStateListOf import org.briarproject.bramble.api.connection.ConnectionRegistry import org.briarproject.bramble.api.contact.Contact import org.briarproject.bramble.api.contact.ContactId @@ -25,17 +26,18 @@ abstract class ContactsViewModel( private val LOG = Logger.getLogger(ContactsViewModel::class.java.name) } - protected val _contactList = mutableListOf<ContactItem>() + private val _fullContactList = mutableListOf<ContactItem>() + private val _filteredContactList = mutableStateListOf<ContactItem>() - abstract val contactList: List<ContactItem> + val contactList: List<ContactItem> = _filteredContactList protected open fun filterContact(contact: Contact) = true open fun loadContacts() { - _contactList.apply { + _fullContactList.apply { clear() addAll( - contactManager.contacts.filter(::filterContact).map { contact -> + contactManager.contacts.map { contact -> ContactItem( contact, connectionRegistry.isConnected(contact.id), @@ -44,6 +46,15 @@ abstract class ContactsViewModel( } ) } + updateFilteredList() + } + + // todo: when migrated to StateFlow, this could be done implicitly instead + protected open fun updateFilteredList() { + _filteredContactList.apply { + clear() + addAll(_fullContactList.filter { filterContact(it.contact) }) + } } override fun eventOccurred(e: Event?) { @@ -68,10 +79,12 @@ abstract class ContactsViewModel( } protected open fun updateItem(contactId: ContactId, update: (ContactItem) -> ContactItem) { - _contactList.replaceFirst({ it.contact.id == contactId }, update) + _fullContactList.replaceFirst({ it.contact.id == contactId }, update) + updateFilteredList() } protected open fun removeItem(contactId: ContactId) { - _contactList.removeFirst { it.contact.id == contactId } + _fullContactList.removeFirst { it.contact.id == contactId } + updateFilteredList() } } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/conversation/PrivateMessageView.kt b/src/main/kotlin/org/briarproject/briar/desktop/conversation/PrivateMessageView.kt index ae06e0135a..b9dc764418 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/conversation/PrivateMessageView.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/conversation/PrivateMessageView.kt @@ -25,7 +25,7 @@ fun PrivateMessageView( Column(modifier = Modifier.weight(1f).fillMaxHeight()) { contactListViewModel.selectedContact.value?.also { selectedContact -> Conversation( - selectedContact.contact, + selectedContact, introductionViewModel ) } ?: UiPlaceholder() diff --git a/src/main/kotlin/org/briarproject/briar/desktop/introduction/IntroductionViewModel.kt b/src/main/kotlin/org/briarproject/briar/desktop/introduction/IntroductionViewModel.kt index 3b2e3f393c..fda0aa64dc 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/introduction/IntroductionViewModel.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/introduction/IntroductionViewModel.kt @@ -7,7 +7,6 @@ import org.briarproject.bramble.api.contact.Contact import org.briarproject.bramble.api.contact.ContactManager import org.briarproject.bramble.api.event.EventBus import org.briarproject.briar.api.conversation.ConversationManager -import org.briarproject.briar.desktop.contact.ContactItem import org.briarproject.briar.desktop.contact.ContactsViewModel import java.util.logging.Logger import javax.inject.Inject @@ -35,7 +34,6 @@ constructor( private val _secondScreen = mutableStateOf(false) private val _introductionMessage = mutableStateOf("") - override val contactList: List<ContactItem> = _contactList val firstContact: State<Contact?> = _firstContact val secondContact: State<Contact?> = _secondContact val secondScreen: State<Boolean> = _secondScreen @@ -54,6 +52,7 @@ constructor( fun backToFirstScreen() { _secondScreen.value = false + _introductionMessage.value = "" } fun setIntroductionMessage(msg: String) { @@ -61,6 +60,6 @@ constructor( } override fun filterContact(contact: Contact): Boolean { - return _firstContact.value!!.id != contact.id + return _firstContact.value?.id != contact.id } } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt b/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt index afbda2623f..f621dab9eb 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt @@ -104,7 +104,6 @@ constructor( when (screenState) { Screen.REGISTRATION -> Registration(registrationViewModel) { - contactListViewModel.loadContacts() screenState = Screen.MAIN } Screen.LOGIN -> -- GitLab