🛠️ Fix SearchTextField

* Async onQueryChange
This commit is contained in:
Acclorite 2025-03-05 17:59:10 +02:00
parent b57434aaa3
commit 78b3b04df3
4 changed files with 35 additions and 10 deletions

View file

@ -130,7 +130,7 @@ fun BrowseTopBar(
.onGloballyPositioned { .onGloballyPositioned {
requestFocus(BrowseEvent.OnRequestFocus(focusRequester)) requestFocus(BrowseEvent.OnRequestFocus(focusRequester))
}, },
query = searchQuery, initialQuery = searchQuery,
onQueryChange = { onQueryChange = {
searchQueryChange(BrowseEvent.OnSearchQueryChange(it)) searchQueryChange(BrowseEvent.OnSearchQueryChange(it))
}, },

View file

@ -12,6 +12,10 @@ import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
@ -20,6 +24,9 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardCapitalization
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.debounce
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
/** /**
@ -27,21 +34,36 @@ import ua.acclorite.book_story.R
* Used in main screens for searching. * Used in main screens for searching.
* *
* @param modifier Modifier to apply. * @param modifier Modifier to apply.
* @param query Search query. * @param initialQuery Initial search query.
* @param onQueryChange Callback to change [query]. * @param onQueryChange Callback to change query.
* @param onSearch Search action (refresh list, fetch filtered books etc..). * @param onSearch Search action (refresh list, fetch filtered books etc..).
*/ */
@OptIn(FlowPreview::class)
@Composable @Composable
fun SearchTextField( fun SearchTextField(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
query: String, initialQuery: String,
onQueryChange: (String) -> Unit, onQueryChange: (String) -> Unit,
onSearch: () -> Unit onSearch: () -> Unit
) { ) {
val keyboardManager = LocalSoftwareKeyboardController.current val keyboardManager = LocalSoftwareKeyboardController.current
val query = remember {
mutableStateOf(initialQuery)
}
LaunchedEffect(query) {
snapshotFlow {
query.value
}.debounce(50).collectLatest {
if (it == initialQuery) return@collectLatest
onQueryChange(it)
}
}
BasicTextField( BasicTextField(
value = query, value = query.value,
singleLine = true, singleLine = true,
textStyle = TextStyle( textStyle = TextStyle(
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
@ -50,13 +72,16 @@ fun SearchTextField(
fontFamily = MaterialTheme.typography.titleLarge.fontFamily fontFamily = MaterialTheme.typography.titleLarge.fontFamily
), ),
modifier = modifier, modifier = modifier,
onValueChange = onQueryChange, onValueChange = {
query.value = it
},
keyboardOptions = KeyboardOptions( keyboardOptions = KeyboardOptions(
KeyboardCapitalization.Words, KeyboardCapitalization.Sentences,
imeAction = ImeAction.Search imeAction = ImeAction.Search
), ),
keyboardActions = KeyboardActions( keyboardActions = KeyboardActions(
onSearch = { onSearch = {
onQueryChange(query.value)
onSearch() onSearch()
keyboardManager?.hide() keyboardManager?.hide()
} }
@ -64,7 +89,7 @@ fun SearchTextField(
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant) cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant)
) { innerText -> ) { innerText ->
Box(contentAlignment = Alignment.CenterStart) { Box(contentAlignment = Alignment.CenterStart) {
if (query.isEmpty()) { if (query.value.isEmpty()) {
StyledText( StyledText(
text = stringResource(id = R.string.search_field_empty), text = stringResource(id = R.string.search_field_empty),
style = MaterialTheme.typography.titleLarge.copy( style = MaterialTheme.typography.titleLarge.copy(

View file

@ -100,7 +100,7 @@ fun HistoryTopBar(
.onGloballyPositioned { .onGloballyPositioned {
requestFocus(HistoryEvent.OnRequestFocus(focusRequester)) requestFocus(HistoryEvent.OnRequestFocus(focusRequester))
}, },
query = searchQuery, initialQuery = searchQuery,
onQueryChange = { onQueryChange = {
searchQueryChange(HistoryEvent.OnSearchQueryChange(it)) searchQueryChange(HistoryEvent.OnSearchQueryChange(it))
}, },

View file

@ -133,7 +133,7 @@ fun LibraryTopBar(
.onGloballyPositioned { .onGloballyPositioned {
requestFocus(LibraryEvent.OnRequestFocus(focusRequester)) requestFocus(LibraryEvent.OnRequestFocus(focusRequester))
}, },
query = searchQuery, initialQuery = searchQuery,
onQueryChange = { onQueryChange = {
searchQueryChange(LibraryEvent.OnSearchQueryChange(it)) searchQueryChange(LibraryEvent.OnSearchQueryChange(it))
}, },