Implement searchbar + initial extension search

This commit is contained in:
Syer10
2021-05-07 22:30:15 -04:00
parent 199ecd42c6
commit f1caf335e1
3 changed files with 89 additions and 40 deletions

View File

@@ -6,23 +6,40 @@
package ca.gosyer.ui.base.components
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
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.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material.AppBarDefaults
import androidx.compose.material.Card
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ca.gosyer.ui.main.Route
import com.github.zsoltk.compose.router.BackStack
import compose.icons.FontAwesomeIcons
@@ -36,19 +53,50 @@ fun Toolbar(
closable: Boolean,
modifier: Modifier = Modifier,
actions: @Composable RowScope.() -> Unit = {},
backgroundColor: Color = MaterialTheme.colors.primary, // CustomColors.current.bars,
contentColor: Color = MaterialTheme.colors.onPrimary, // CustomColors.current.onBars,
backgroundColor: Color = MaterialTheme.colors.surface, // CustomColors.current.bars,
contentColor: Color = contentColorFor(backgroundColor), // CustomColors.current.onBars,
elevation: Dp = AppBarDefaults.TopAppBarElevation,
search: ((String) -> Unit)? = null
) {
val searchText = remember { mutableStateOf("") }
Surface(Modifier.fillMaxWidth().height(32.dp), elevation = 2.dp) {
TopAppBar(
{
Text(name)
},
modifier,
actions = @Composable {
Surface(
modifier = modifier,
elevation = elevation,
shape = RectangleShape,
color = backgroundColor,
contentColor = contentColor
) {
Row(
Modifier.fillMaxWidth().padding(AppBarDefaults.ContentPadding).height(56.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(name, fontSize = 24.sp)
if (search != null) {
Card(
Modifier.fillMaxHeight()
.width(300.dp)
.padding(8.dp),
shape = RoundedCornerShape(4.dp),
elevation = 2.dp,
border = BorderStroke(1.dp, MaterialTheme.colors.primary)
) {
Box(Modifier.fillMaxSize().padding(8.dp), Alignment.CenterStart) {
BasicTextField(
searchText.value,
onValueChange = {
searchText.value = it
search(it)
},
singleLine = true,
modifier = Modifier.fillMaxWidth(),
textStyle = TextStyle(contentColor, 18.sp),
cursorBrush = SolidColor(contentColor.copy(alpha = 0.50F))
)
}
}
}
Row {
actions()
if (closable) {
IconButton(
@@ -56,34 +104,10 @@ fun Toolbar(
router?.pop()
}
) {
Icon(FontAwesomeIcons.Regular.WindowClose, "close")
Icon(FontAwesomeIcons.Regular.WindowClose, "close", Modifier.size(52.dp))
}
}
},
backgroundColor = backgroundColor,
contentColor = contentColor,
elevation = elevation
)
/*Row(Modifier.fillMaxSize(), horizontalArrangement = Arrangement.SpaceBetween) {
Text(name, fontSize = 24.sp)
if (search != null) {
BasicTextField(
searchText.value,
onValueChange = {
searchText.value = it
search(it)
}
)
}
if (closable) {
IconButton(
onClick = {
router?.pop()
}
) {
Icon(FontAwesomeIcons.Regular.WindowClose, "close", Modifier.size(32.dp))
}
}
}*/
}
}
}

View File

@@ -43,6 +43,7 @@ import androidx.compose.ui.unit.sp
import ca.gosyer.data.models.Extension
import ca.gosyer.ui.base.components.KtorImage
import ca.gosyer.ui.base.components.LoadingScreen
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.vm.viewModel
import ca.gosyer.util.compose.ThemedWindow
@@ -61,7 +62,7 @@ fun ExtensionsMenu() {
val serverUrl by vm.serverUrl.collectAsState()
Box(Modifier.fillMaxSize().background(MaterialTheme.colors.background)) {
if (extensions.isEmpty()) {
if (isLoading) {
LoadingScreen(isLoading)
} else {
val state = rememberLazyListState()
@@ -69,6 +70,15 @@ fun ExtensionsMenu() {
Box(Modifier.fillMaxSize()) {
LazyColumn(Modifier.fillMaxSize().padding(end = 12.dp), state) {
item {
Toolbar(
"Extensions",
closable = false,
search = {
vm.search(it)
}
)
}
items(extensions) { extension ->
ExtensionItem(
extension,
@@ -87,7 +97,7 @@ fun ExtensionsMenu() {
modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
adapter = rememberScrollbarAdapter(
scrollState = state,
itemCount = itemCount,
itemCount = itemCount + 1, // Plus toolbar,
averageItemSize = 37.dp // TextBox height + Spacer height
)
)

View File

@@ -27,6 +27,8 @@ class ExtensionsMenuViewModel @Inject constructor(
val serverUrl = serverPreferences.server().stateIn(scope)
private lateinit var extensionList: List<Extension>
private val _extensions = MutableStateFlow(emptyList<Extension>())
val extensions = _extensions.asStateFlow()
@@ -43,8 +45,8 @@ class ExtensionsMenuViewModel @Inject constructor(
try {
_isLoading.value = true
val enabledLangs = extensionPreferences.languages().get()
val extensions = extensionHandler.getExtensionList()
_extensions.value = extensions.filter { it.lang in enabledLangs }.sortedWith(compareBy({ it.lang }, { it.pkgName }))
extensionList = extensionHandler.getExtensionList()
_extensions.value = extensionList.filter { it.lang in enabledLangs }.sortedWith(compareBy({ it.lang }, { it.pkgName }))
} catch (e: Exception) {
if (e is CancellationException) throw e
} finally {
@@ -75,4 +77,17 @@ class ExtensionsMenuViewModel @Inject constructor(
getExtensions()
}
}
fun search(searchQuery: String) {
if (searchQuery.isBlank()) {
_extensions.value = extensionList
} else {
val queries = searchQuery.split(" ")
val extensions = extensionList.toMutableList()
queries.forEach { query ->
extensions.removeIf { !it.name.contains(query, true) }
}
_extensions.value = extensions.toList()
}
}
}