diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt index f7f6bff50d06c0190407b3872c65f193bbf2a56d..be304ce31c545f63455b93d24b567d73b9b7f57d 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/contact/ContactList.kt @@ -33,6 +33,8 @@ import androidx.compose.foundation.rememberScrollbarAdapter import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.PersonAdd import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -65,9 +67,11 @@ fun ContactList( modifier = Modifier.fillMaxWidth().height(HEADER_SIZE + 1.dp), ) { SearchTextField( - filterBy, + placeholder = i18n("contacts.search.title"), + icon = Icons.Filled.PersonAdd, + searchValue = filterBy, onValueChange = setFilterBy, - onContactAdd = onContactAdd, + onAddButtonClicked = onContactAdd, ) } diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/contact/SearchTextField.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/contact/SearchTextField.kt index cbfa8141ef5e7afc5e69408b09763e246320da71..6d3e564dfb76184dfd532e37f97ecea736287ae5 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/contact/SearchTextField.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/contact/SearchTextField.kt @@ -27,17 +27,23 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.TextField import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.PersonAdd import androidx.compose.material.icons.filled.Search import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp import org.briarproject.briar.desktop.ui.ColoredIconButton import org.briarproject.briar.desktop.utils.AccessibilityUtils.description import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n @Composable -fun SearchTextField(searchValue: String, onValueChange: (String) -> Unit, onContactAdd: () -> Unit) { +fun SearchTextField( + placeholder: String, + icon: ImageVector, + searchValue: String, + onValueChange: (String) -> Unit, + onAddButtonClicked: () -> Unit, +) { TextField( value = searchValue, onValueChange = onValueChange, @@ -45,7 +51,7 @@ fun SearchTextField(searchValue: String, onValueChange: (String) -> Unit, onCont textStyle = LocalTextStyle.current.copy( color = MaterialTheme.colors.onSurface ), - placeholder = { Text(i18n("contacts.search.title"), style = MaterialTheme.typography.body1) }, + placeholder = { Text(placeholder, style = MaterialTheme.typography.body1) }, shape = RoundedCornerShape(0.dp), leadingIcon = { val padding = Modifier.padding(top = 8.dp, bottom = 8.dp, start = 32.dp, end = 4.dp) @@ -53,10 +59,10 @@ fun SearchTextField(searchValue: String, onValueChange: (String) -> Unit, onCont }, trailingIcon = { ColoredIconButton( - icon = Icons.Filled.PersonAdd, + icon = icon, iconSize = 20.dp, contentDescription = i18n("access.contacts.add"), - onClick = onContactAdd, + onClick = onAddButtonClicked, modifier = Modifier.padding(end = 8.dp) ) }, diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsList.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsList.kt index 067be793c12e28e53802991fcc409da846cb6806..437b5bdc06c3883e69aea292099aebe2ec3a558d 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsList.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsList.kt @@ -18,40 +18,81 @@ package org.briarproject.briar.desktop.forums +import androidx.compose.foundation.VerticalScrollbar +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +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.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.rememberScrollbarAdapter +import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material.MaterialTheme -import androidx.compose.material.Scaffold +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.unit.dp import org.briarproject.bramble.api.sync.GroupId +import org.briarproject.briar.desktop.contact.SearchTextField import org.briarproject.briar.desktop.theme.surfaceVariant +import org.briarproject.briar.desktop.ui.Constants import org.briarproject.briar.desktop.ui.Constants.COLUMN_WIDTH import org.briarproject.briar.desktop.ui.HorizontalDivider +import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n @Composable fun ForumsList( - list: List<ForumsItem>, + list: State<List<GroupItem>>, isSelected: (GroupId) -> Boolean, + filterBy: State<String>, + onFilterSet: (String) -> Unit, onGroupIdSelected: (GroupId) -> Unit, + onAddButtonClicked: () -> Unit, ) { - // TODO AddForumDialog (and search bar?) - Scaffold( + val scrollState = rememberLazyListState() + Surface( modifier = Modifier.fillMaxHeight().width(COLUMN_WIDTH), - backgroundColor = MaterialTheme.colors.surfaceVariant, - content = { - LazyColumn { - items(list) { item -> - GroupsCard( - item = item, - onGroupIdSelected = onGroupIdSelected, - selected = isSelected(item.forum.id) - ) - HorizontalDivider() + color = MaterialTheme.colors.surfaceVariant + ) { + Column { + Column( + modifier = Modifier.fillMaxWidth().height(Constants.HEADER_SIZE + 1.dp), + ) { + SearchTextField( + placeholder = i18n("forum.search.title"), + icon = Icons.Filled.AddComment, + searchValue = filterBy.value, + onValueChange = onFilterSet, + onAddButtonClicked = onAddButtonClicked, + ) + } + Box(modifier = Modifier.fillMaxSize()) { + LazyColumn( + state = scrollState, + modifier = Modifier.selectableGroup() + ) { + items(list.value) { item -> + GroupsCard( + item = item, + onGroupIdSelected = onGroupIdSelected, + selected = isSelected(item.id) + ) + HorizontalDivider() + } } + VerticalScrollbar( + adapter = rememberScrollbarAdapter(scrollState), + modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight() + ) } - }, - ) + } + } } diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsScreen.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsScreen.kt index f1a6509dcc55bbbb9d733857aa31c1683988d1de..77f448ddf8fe2cf9b6b89081d4f918d9020ed666 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsScreen.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsScreen.kt @@ -36,7 +36,10 @@ fun ForumsScreen( ForumsList( list = viewModel.groupList, isSelected = viewModel::isSelected, + filterBy = viewModel.filterBy, + onFilterSet = viewModel::setFilterBy, onGroupIdSelected = viewModel::selectGroup, + onAddButtonClicked = {}, ) VerticalDivider() Column(modifier = Modifier.weight(1f).fillMaxHeight()) { diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsViewModel.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsViewModel.kt index ea998d3efbeab7d963227a3953013d01321961ca..b92f33acdbf46732c515a1a01e6af62cacd17b8b 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsViewModel.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/forums/ForumsViewModel.kt @@ -19,6 +19,7 @@ package org.briarproject.briar.desktop.forums import androidx.compose.runtime.State +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import org.briarproject.bramble.api.db.TransactionManager @@ -30,6 +31,7 @@ import org.briarproject.briar.api.forum.ForumManager import org.briarproject.briar.desktop.threading.BriarExecutors import org.briarproject.briar.desktop.utils.clearAndAddAll import org.briarproject.briar.desktop.viewmodel.EventListenerDbViewModel +import org.briarproject.briar.desktop.viewmodel.asState import javax.inject.Inject class ForumsViewModel @@ -43,11 +45,19 @@ constructor( ) : EventListenerDbViewModel(briarExecutors, lifecycleManager, db, eventBus) { private val _fullGroupList = mutableStateListOf<ForumsItem>() - val groupList: List<ForumsItem> = _fullGroupList + val groupList = derivedStateOf { + val filter = _filterBy.value + _fullGroupList.filter { item -> + item.name.contains(filter, ignoreCase = true) + }.sortedByDescending { it.timestamp } + } private val _selectedGroupId = mutableStateOf<GroupId?>(null) val selectedGroupId: State<GroupId?> = _selectedGroupId + private val _filterBy = mutableStateOf("") + val filterBy = _filterBy.asState() + override fun onInit() { super.onInit() loadGroups() @@ -76,4 +86,8 @@ constructor( } fun isSelected(privateGroupId: GroupId) = _selectedGroupId.value == privateGroupId + + fun setFilterBy(filter: String) { + _filterBy.value = filter + } } diff --git a/briar-desktop/src/main/resources/strings/BriarDesktop.properties b/briar-desktop/src/main/resources/strings/BriarDesktop.properties index f82aa0b2a7cd06a2848f8e52ef6a6f7f05661d17..47f782afa9cbb2ce90d4da10f13541003588c5c2 100644 --- a/briar-desktop/src/main/resources/strings/BriarDesktop.properties +++ b/briar-desktop/src/main/resources/strings/BriarDesktop.properties @@ -101,6 +101,7 @@ conversation.change.alias.dialog.title=Change contact name conversation.change.alias.dialog.description=Please enter a new name for this contact (only visible to you): # Forums +forum.search.title=Forums group.card.posts={0, plural, one {{0} post} other {{0} posts}} # Private Groups