Reduce recompositions on search screen

pull/1964/head
ivan 5 days ago
parent f93da9c7a5
commit a97e52e377

@ -51,7 +51,9 @@ import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -105,10 +107,10 @@ internal fun SearchRoute(
) { ) {
val recentSearchQueriesUiState by searchViewModel.recentSearchQueriesUiState.collectAsStateWithLifecycle() val recentSearchQueriesUiState by searchViewModel.recentSearchQueriesUiState.collectAsStateWithLifecycle()
val searchResultUiState by searchViewModel.searchResultUiState.collectAsStateWithLifecycle() val searchResultUiState by searchViewModel.searchResultUiState.collectAsStateWithLifecycle()
val searchQuery by searchViewModel.searchQuery.collectAsStateWithLifecycle() val searchQueryState = searchViewModel.searchQuery.collectAsStateWithLifecycle()
SearchScreen( SearchScreen(
modifier = modifier, modifier = modifier,
searchQuery = searchQuery, searchQueryState = searchQueryState,
recentSearchesUiState = recentSearchQueriesUiState, recentSearchesUiState = recentSearchQueriesUiState,
searchResultUiState = searchResultUiState, searchResultUiState = searchResultUiState,
onSearchQueryChanged = searchViewModel::onSearchQueryChanged, onSearchQueryChanged = searchViewModel::onSearchQueryChanged,
@ -126,7 +128,7 @@ internal fun SearchRoute(
@Composable @Composable
internal fun SearchScreen( internal fun SearchScreen(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
searchQuery: String = "", searchQueryState: State<String> = remember { mutableStateOf("") },
recentSearchesUiState: RecentSearchQueriesUiState = RecentSearchQueriesUiState.Loading, recentSearchesUiState: RecentSearchQueriesUiState = RecentSearchQueriesUiState.Loading,
searchResultUiState: SearchResultUiState = SearchResultUiState.Loading, searchResultUiState: SearchResultUiState = SearchResultUiState.Loading,
onSearchQueryChanged: (String) -> Unit = {}, onSearchQueryChanged: (String) -> Unit = {},
@ -146,16 +148,16 @@ internal fun SearchScreen(
onBackClick = onBackClick, onBackClick = onBackClick,
onSearchQueryChanged = onSearchQueryChanged, onSearchQueryChanged = onSearchQueryChanged,
onSearchTriggered = onSearchTriggered, onSearchTriggered = onSearchTriggered,
searchQuery = searchQuery, searchQueryState = searchQueryState,
) )
when (searchResultUiState) { when (searchResultUiState) {
SearchResultUiState.Loading, SearchResultUiState.Loading,
SearchResultUiState.LoadFailed, SearchResultUiState.LoadFailed,
-> Unit -> Unit
SearchResultUiState.SearchNotReady -> SearchNotReadyBody() SearchResultUiState.SearchNotReady -> SearchNotReadyBody()
SearchResultUiState.EmptyQuery, SearchResultUiState.EmptyQuery,
-> { -> {
if (recentSearchesUiState is RecentSearchQueriesUiState.Success) { if (recentSearchesUiState is RecentSearchQueriesUiState.Success) {
RecentSearchesBody( RecentSearchesBody(
onClearRecentSearches = onClearRecentSearches, onClearRecentSearches = onClearRecentSearches,
@ -171,7 +173,7 @@ internal fun SearchScreen(
is SearchResultUiState.Success -> { is SearchResultUiState.Success -> {
if (searchResultUiState.isEmpty()) { if (searchResultUiState.isEmpty()) {
EmptySearchResultBody( EmptySearchResultBody(
searchQuery = searchQuery, searchQueryState = searchQueryState,
onInterestsClick = onInterestsClick, onInterestsClick = onInterestsClick,
) )
if (recentSearchesUiState is RecentSearchQueriesUiState.Success) { if (recentSearchesUiState is RecentSearchQueriesUiState.Success) {
@ -186,7 +188,7 @@ internal fun SearchScreen(
} }
} else { } else {
SearchResultBody( SearchResultBody(
searchQuery = searchQuery, searchQueryState = searchQueryState,
topics = searchResultUiState.topics, topics = searchResultUiState.topics,
newsResources = searchResultUiState.newsResources, newsResources = searchResultUiState.newsResources,
onSearchTriggered = onSearchTriggered, onSearchTriggered = onSearchTriggered,
@ -204,13 +206,14 @@ internal fun SearchScreen(
@Composable @Composable
fun EmptySearchResultBody( fun EmptySearchResultBody(
searchQuery: String, searchQueryState: State<String>,
onInterestsClick: () -> Unit, onInterestsClick: () -> Unit,
) { ) {
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(horizontal = 48.dp), modifier = Modifier.padding(horizontal = 48.dp),
) { ) {
val searchQuery = searchQueryState.value
val message = stringResource(id = searchR.string.feature_search_result_not_found, searchQuery) val message = stringResource(id = searchR.string.feature_search_result_not_found, searchQuery)
val start = message.indexOf(searchQuery) val start = message.indexOf(searchQuery)
Text( Text(
@ -283,7 +286,7 @@ private fun SearchNotReadyBody() {
@Composable @Composable
private fun SearchResultBody( private fun SearchResultBody(
searchQuery: String, searchQueryState: State<String>,
topics: List<FollowableTopic>, topics: List<FollowableTopic>,
newsResources: List<UserNewsResource>, newsResources: List<UserNewsResource>,
onSearchTriggered: (String) -> Unit, onSearchTriggered: (String) -> Unit,
@ -334,7 +337,7 @@ private fun SearchResultBody(
topicImageUrl = followableTopic.topic.imageUrl, topicImageUrl = followableTopic.topic.imageUrl,
onClick = { onClick = {
// Pass the current search query to ViewModel to save it as recent searches // Pass the current search query to ViewModel to save it as recent searches
onSearchTriggered(searchQuery) onSearchTriggered(searchQueryState.value)
onTopicClick(topicId) onTopicClick(topicId)
}, },
onFollowButtonClick = { onFollowButtonClick(topicId, it) }, onFollowButtonClick = { onFollowButtonClick(topicId, it) },
@ -363,7 +366,7 @@ private fun SearchResultBody(
onNewsResourceViewed = onNewsResourceViewed, onNewsResourceViewed = onNewsResourceViewed,
onTopicClick = onTopicClick, onTopicClick = onTopicClick,
onExpandedCardClick = { onExpandedCardClick = {
onSearchTriggered(searchQuery) onSearchTriggered(searchQueryState.value)
}, },
) )
} }
@ -441,7 +444,7 @@ private fun RecentSearchesBody(
@Composable @Composable
private fun SearchToolbar( private fun SearchToolbar(
searchQuery: String, searchQueryState: State<String>,
onSearchQueryChanged: (String) -> Unit, onSearchQueryChanged: (String) -> Unit,
onSearchTriggered: (String) -> Unit, onSearchTriggered: (String) -> Unit,
onBackClick: () -> Unit, onBackClick: () -> Unit,
@ -462,23 +465,24 @@ private fun SearchToolbar(
SearchTextField( SearchTextField(
onSearchQueryChanged = onSearchQueryChanged, onSearchQueryChanged = onSearchQueryChanged,
onSearchTriggered = onSearchTriggered, onSearchTriggered = onSearchTriggered,
searchQuery = searchQuery, searchQueryState = searchQueryState,
) )
} }
} }
@Composable @Composable
private fun SearchTextField( private fun SearchTextField(
searchQuery: String, searchQueryState: State<String>,
onSearchQueryChanged: (String) -> Unit, onSearchQueryChanged: (String) -> Unit,
onSearchTriggered: (String) -> Unit, onSearchTriggered: (String) -> Unit,
) { ) {
val searchQuery = searchQueryState.value
val focusRequester = remember { FocusRequester() } val focusRequester = remember { FocusRequester() }
val keyboardController = LocalSoftwareKeyboardController.current val keyboardController = LocalSoftwareKeyboardController.current
val onSearchExplicitlyTriggered = { val onSearchExplicitlyTriggered = {
keyboardController?.hide() keyboardController?.hide()
onSearchTriggered(searchQuery) onSearchTriggered(searchQueryState.value)
} }
TextField( TextField(
@ -554,7 +558,7 @@ private fun SearchTextField(
private fun SearchToolbarPreview() { private fun SearchToolbarPreview() {
NiaTheme { NiaTheme {
SearchToolbar( SearchToolbar(
searchQuery = "", searchQueryState = remember { mutableStateOf("") },
onBackClick = {}, onBackClick = {},
onSearchQueryChanged = {}, onSearchQueryChanged = {},
onSearchTriggered = {}, onSearchTriggered = {},
@ -568,7 +572,7 @@ private fun EmptySearchResultColumnPreview() {
NiaTheme { NiaTheme {
EmptySearchResultBody( EmptySearchResultBody(
onInterestsClick = {}, onInterestsClick = {},
searchQuery = "C++", searchQueryState = remember { mutableStateOf("C++") },
) )
} }
} }

Loading…
Cancel
Save