From 78b3b04df312e232e41c3320d76f97048fe35af9 Mon Sep 17 00:00:00 2001 From: Acclorite <140836141+Acclorite@users.noreply.github.com> Date: Wed, 5 Mar 2025 17:59:10 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A0=EF=B8=8F=20Fix=20SearchTextField?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Async onQueryChange --- .../presentation/browse/BrowseTopBar.kt | 2 +- .../core/components/common/SearchTextField.kt | 39 +++++++++++++++---- .../presentation/history/HistoryTopBar.kt | 2 +- .../presentation/library/LibraryTopBar.kt | 2 +- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/browse/BrowseTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/browse/BrowseTopBar.kt index 792757b2..593df2e9 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/browse/BrowseTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/browse/BrowseTopBar.kt @@ -130,7 +130,7 @@ fun BrowseTopBar( .onGloballyPositioned { requestFocus(BrowseEvent.OnRequestFocus(focusRequester)) }, - query = searchQuery, + initialQuery = searchQuery, onQueryChange = { searchQueryChange(BrowseEvent.OnSearchQueryChange(it)) }, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/core/components/common/SearchTextField.kt b/app/src/main/java/ua/acclorite/book_story/presentation/core/components/common/SearchTextField.kt index 6bb3f598..997162f3 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/core/components/common/SearchTextField.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/core/components/common/SearchTextField.kt @@ -12,6 +12,10 @@ import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.MaterialTheme 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.Modifier 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.input.ImeAction 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 /** @@ -27,21 +34,36 @@ import ua.acclorite.book_story.R * Used in main screens for searching. * * @param modifier Modifier to apply. - * @param query Search query. - * @param onQueryChange Callback to change [query]. + * @param initialQuery Initial search query. + * @param onQueryChange Callback to change query. * @param onSearch Search action (refresh list, fetch filtered books etc..). */ +@OptIn(FlowPreview::class) @Composable fun SearchTextField( modifier: Modifier = Modifier, - query: String, + initialQuery: String, onQueryChange: (String) -> Unit, onSearch: () -> Unit ) { 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( - value = query, + value = query.value, singleLine = true, textStyle = TextStyle( color = MaterialTheme.colorScheme.onSurface, @@ -50,13 +72,16 @@ fun SearchTextField( fontFamily = MaterialTheme.typography.titleLarge.fontFamily ), modifier = modifier, - onValueChange = onQueryChange, + onValueChange = { + query.value = it + }, keyboardOptions = KeyboardOptions( - KeyboardCapitalization.Words, + KeyboardCapitalization.Sentences, imeAction = ImeAction.Search ), keyboardActions = KeyboardActions( onSearch = { + onQueryChange(query.value) onSearch() keyboardManager?.hide() } @@ -64,7 +89,7 @@ fun SearchTextField( cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant) ) { innerText -> Box(contentAlignment = Alignment.CenterStart) { - if (query.isEmpty()) { + if (query.value.isEmpty()) { StyledText( text = stringResource(id = R.string.search_field_empty), style = MaterialTheme.typography.titleLarge.copy( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/history/HistoryTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/history/HistoryTopBar.kt index 0197836c..506043be 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/history/HistoryTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/history/HistoryTopBar.kt @@ -100,7 +100,7 @@ fun HistoryTopBar( .onGloballyPositioned { requestFocus(HistoryEvent.OnRequestFocus(focusRequester)) }, - query = searchQuery, + initialQuery = searchQuery, onQueryChange = { searchQueryChange(HistoryEvent.OnSearchQueryChange(it)) }, diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryTopBar.kt index f308bb54..37ee888a 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/library/LibraryTopBar.kt @@ -133,7 +133,7 @@ fun LibraryTopBar( .onGloballyPositioned { requestFocus(LibraryEvent.OnRequestFocus(focusRequester)) }, - query = searchQuery, + initialQuery = searchQuery, onQueryChange = { searchQueryChange(LibraryEvent.OnSearchQueryChange(it)) },