mirror of
https://github.com/smyalygames/vegan-e-numbers.git
synced 2025-05-18 17:04:14 +02:00
feat(app): improve search function by removing search suggestions
This commit is contained in:
parent
1b94c0a694
commit
64c2e13a6f
@ -1,15 +1,10 @@
|
|||||||
package component
|
package component
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedContent
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.Clear
|
import androidx.compose.material.icons.filled.Clear
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
@ -27,13 +22,11 @@ import androidx.compose.ui.semantics.traversalIndex
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
import data.ENumber
|
|
||||||
import tab.Licenses
|
import tab.Licenses
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun Search(eNumbers: List<ENumber>) {
|
fun Search(text: MutableState<String>) {
|
||||||
var text by rememberSaveable { mutableStateOf("") }
|
|
||||||
var expanded by rememberSaveable { mutableStateOf(false) }
|
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||||
val menuExpanded = remember { mutableStateOf(false) }
|
val menuExpanded = remember { mutableStateOf(false) }
|
||||||
|
|
||||||
@ -47,32 +40,24 @@ fun Search(eNumbers: List<ENumber>) {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.CenterHorizontally)
|
.align(Alignment.CenterHorizontally)
|
||||||
.semantics { traversalIndex = 0f },
|
.semantics { traversalIndex = 0f },
|
||||||
query = text,
|
query = text.value,
|
||||||
onQueryChange = { text = it },
|
onQueryChange = { text.value = it },
|
||||||
onSearch = { expanded = false },
|
onSearch = { expanded = false },
|
||||||
onActiveChange = { expanded = it },
|
onActiveChange = { /* Do nothing */ },
|
||||||
active = expanded,
|
active = expanded,
|
||||||
placeholder = { Text("Search E Numbers") },
|
placeholder = { Text("Search E Numbers") },
|
||||||
leadingIcon = {
|
leadingIcon = {
|
||||||
IconButton(
|
IconButton(
|
||||||
enabled = expanded,
|
enabled = false,
|
||||||
onClick = { if (expanded) expanded = false }
|
onClick = { /* Do nothing */ }
|
||||||
) {
|
) {
|
||||||
AnimatedContent(
|
|
||||||
targetState = expanded,
|
|
||||||
) { targetExpanded ->
|
|
||||||
if (targetExpanded) {
|
|
||||||
Icon(Icons.AutoMirrored.Filled.ArrowBack, "Exit Search")
|
|
||||||
} else {
|
|
||||||
Icon(Icons.Filled.Search, "Navigation Menu")
|
Icon(Icons.Filled.Search, "Navigation Menu")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Row {
|
Row {
|
||||||
if (text.isNotEmpty()) {
|
if (text.value.isNotEmpty()) {
|
||||||
IconButton(onClick = { text = "" }) {
|
IconButton(onClick = { text.value = "" }) {
|
||||||
Icon(imageVector = Icons.Filled.Clear, contentDescription = "Clear Search")
|
Icon(imageVector = Icons.Filled.Clear, contentDescription = "Clear Search")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,22 +69,7 @@ fun Search(eNumbers: List<ENumber>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) { /* No search content - done externally */ }
|
||||||
Column(Modifier.verticalScroll(rememberScrollState())) {
|
|
||||||
searchSuggestion(query = text, eNumbers = eNumbers).forEach {
|
|
||||||
ListItem(
|
|
||||||
headlineContent = { Text(text = it.number) },
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable {
|
|
||||||
text = it.number
|
|
||||||
expanded = false
|
|
||||||
}
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 16.dp, vertical = 4.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,15 +98,3 @@ private fun OptionsMenu(expanded: MutableState<Boolean>) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun searchSuggestion(query: String, eNumbers: List<ENumber>): List<ENumber> {
|
|
||||||
if (query.isEmpty()) {
|
|
||||||
return eNumbers
|
|
||||||
}
|
|
||||||
|
|
||||||
val filtered = eNumbers.filter { eNumber ->
|
|
||||||
eNumber.number.contains(query, ignoreCase = true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered
|
|
||||||
}
|
|
||||||
|
@ -2,6 +2,7 @@ package tab.list
|
|||||||
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@ -17,22 +18,42 @@ import androidx.compose.material3.ListItem
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import data.EGroup
|
import data.EGroup
|
||||||
import data.ENumber
|
import data.ENumber
|
||||||
|
|
||||||
class ENumberList(private val eNumbers: List<EGroup>) : Screen {
|
class ENumberList(private val eNumbers: List<EGroup>, private val searchText: MutableState<String>) : Screen {
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
|
val displayItems = searchFilter(query = searchText.value, eGroups = eNumbers)
|
||||||
|
|
||||||
|
println(displayItems)
|
||||||
|
|
||||||
|
if (displayItems.isEmpty()) {
|
||||||
|
Column (
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
Text(text = "Sorry, we couldn't find any results :(")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
LazyColumn(contentPadding = PaddingValues(6.dp)) {
|
LazyColumn(contentPadding = PaddingValues(6.dp)) {
|
||||||
eNumbers.forEach { eGroup ->
|
displayItems.forEach { eGroup ->
|
||||||
|
|
||||||
|
if (displayItems.isNotEmpty()) {
|
||||||
stickyHeader {
|
stickyHeader {
|
||||||
Header(group = eGroup.group)
|
Header(group = eGroup.group)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
items(eGroup.numbers) { eNumber ->
|
items(eGroup.numbers) { eNumber ->
|
||||||
ItemList(eNumber = eNumber)
|
ItemList(eNumber = eNumber)
|
||||||
@ -88,4 +109,18 @@ class ENumberList(private val eNumbers: List<EGroup>) : Screen {
|
|||||||
contentDescription = status
|
contentDescription = status
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun searchFilter(query: String, eGroups: List<EGroup>): List<EGroup> {
|
||||||
|
if (query.isEmpty()) {
|
||||||
|
return eGroups
|
||||||
|
}
|
||||||
|
|
||||||
|
val filtered = eGroups.map { eGroup ->
|
||||||
|
eGroup.copy(numbers = eGroup.numbers.filter { eNumber ->
|
||||||
|
eNumber.number.contains(query, ignoreCase = true)
|
||||||
|
})
|
||||||
|
}.filter { it.numbers.isNotEmpty() }
|
||||||
|
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import androidx.compose.material3.Scaffold
|
|||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.rememberTopAppBarState
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import cafe.adriel.voyager.core.model.rememberNavigatorScreenModel
|
import cafe.adriel.voyager.core.model.rememberNavigatorScreenModel
|
||||||
@ -38,18 +39,14 @@ object ListMain : Tab {
|
|||||||
val screenModel = navigator.rememberNavigatorScreenModel { ListScreenModel() }
|
val screenModel = navigator.rememberNavigatorScreenModel { ListScreenModel() }
|
||||||
val state by screenModel.state.collectAsState()
|
val state by screenModel.state.collectAsState()
|
||||||
|
|
||||||
|
val searchText = rememberSaveable { mutableStateOf("") }
|
||||||
|
|
||||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
when (val s = state) {
|
Search(text = searchText)
|
||||||
is ListScreenModel.State.Result -> {
|
|
||||||
val ungroupedENumbers = s.eNumbers.flatMap { it.numbers }
|
|
||||||
Search(ungroupedENumbers)
|
|
||||||
}
|
|
||||||
else -> Unit
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
Column(
|
Column(
|
||||||
@ -57,7 +54,7 @@ object ListMain : Tab {
|
|||||||
) {
|
) {
|
||||||
when (val s = state) {
|
when (val s = state) {
|
||||||
is ListScreenModel.State.Loading -> LoadingScreen("E Numbers").Content()
|
is ListScreenModel.State.Loading -> LoadingScreen("E Numbers").Content()
|
||||||
is ListScreenModel.State.Result -> ENumberList(s.eNumbers).Content()
|
is ListScreenModel.State.Result -> ENumberList(s.eNumbers, searchText = searchText).Content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user