Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion composeApp/src/commonMain/kotlin/de/kitshn/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -462,4 +462,37 @@ expect fun closeAppHandler(): () -> Unit

fun String.extractUrl(delimiters: String = " ") = this
.split(delimiters)
.firstOrNull { it.startsWith("http://") || it.startsWith("https://") }
.firstOrNull { it.startsWith("http://") || it.startsWith("https://") }

/**
* filters and scores a list of elements by a text query on a selected property.
* The priorities are
* 1. exact query match
* 2. a prefix of the property matches the query
* 3. a word boundary substring matches
* 4. a regular substring matches
*
* everything else is not included in the resulting score sorted list
*/
fun <T> filterBySearchQuery(
list: List<T>,
query: String,
selector: (T) -> String
): List<T> {
if (query.isBlank()) return list

return list
.mapNotNull { item ->
val name = selector(item)
val score = when {
name.equals(query, ignoreCase = true) -> 0
name.startsWith(query, ignoreCase = true) -> 1
name.contains(" $query", ignoreCase = true) -> 2
name.contains(query, ignoreCase = true) -> 3
else -> return@mapNotNull null
}
item to score
}
.sortedBy { it.second }
.map { it.first }
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import co.touchlab.kermit.Logger
import de.kitshn.api.tandoor.TandoorClient
import de.kitshn.api.tandoor.TandoorRequestsError
import de.kitshn.api.tandoor.model.TandoorMealType
import de.kitshn.filterBySearchQuery
import kitshn.composeapp.generated.resources.Res
import kitshn.composeapp.generated.resources.common_unknown_meal_type
import org.jetbrains.compose.resources.getString
Expand Down Expand Up @@ -81,6 +82,16 @@ fun BaseMealTypeSearchField(
}
}


val filteredMealTypes = remember(mealTypeList, searchText, selectedMealType) {
if (selectedMealType != null || searchText.isBlank()){
mealTypeList
} else {
// use a priority filtering for better first results
filterBySearchQuery(mealTypeList, searchText) { it.name }
}
}

ExposedDropdownMenuBox(
expanded = isExpanded,
onExpandedChange = {
Expand Down Expand Up @@ -112,7 +123,7 @@ fun BaseMealTypeSearchField(
focus.clearFocus()
}
) {
mealTypeList.forEach {
filteredMealTypes.forEach {
DropdownMenuItem(
text = { Text(it.name) },
onClick = {
Expand Down