Merge pull request #913 from hoangchungk53qx1/main

Refactor Search Feature
pull/870/merge
Adetunji Dahunsi 1 year ago committed by GitHub
commit 4716c7f841
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -19,7 +19,7 @@ package com.google.samples.apps.nowinandroid.feature.search
import com.google.samples.apps.nowinandroid.core.data.model.RecentSearchQuery
sealed interface RecentSearchQueriesUiState {
object Loading : RecentSearchQueriesUiState
data object Loading : RecentSearchQueriesUiState
data class Success(
val recentQueries: List<RecentSearchQuery> = emptyList(),

@ -20,16 +20,16 @@ import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
sealed interface SearchResultUiState {
object Loading : SearchResultUiState
data object Loading : SearchResultUiState
/**
* The state query is empty or too short. To distinguish the state between the
* (initial state or when the search query is cleared) vs the state where no search
* result is returned, explicitly define the empty query state.
*/
object EmptyQuery : SearchResultUiState
data object EmptyQuery : SearchResultUiState
object LoadFailed : SearchResultUiState
data object LoadFailed : SearchResultUiState
data class Success(
val topics: List<FollowableTopic> = emptyList(),
@ -42,5 +42,5 @@ sealed interface SearchResultUiState {
* A state where the search contents are not ready. This happens when the *Fts tables are not
* populated yet.
*/
object SearchNotReady : SearchResultUiState
data object SearchNotReady : SearchResultUiState
}

@ -441,9 +441,7 @@ private fun RecentSearchesBody(
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier
.padding(vertical = 16.dp)
.clickable {
onRecentSearchClicked(recentSearch)
}
.clickable { onRecentSearchClicked(recentSearch) }
.fillMaxWidth(),
)
}

@ -48,46 +48,43 @@ class SearchViewModel @Inject constructor(
private val analyticsHelper: AnalyticsHelper,
) : ViewModel() {
val searchQuery = savedStateHandle.getStateFlow(SEARCH_QUERY, "")
val searchQuery = savedStateHandle.getStateFlow(key = SEARCH_QUERY, initialValue = "")
val searchResultUiState: StateFlow<SearchResultUiState> =
getSearchContentsCountUseCase().flatMapLatest { totalCount ->
if (totalCount < SEARCH_MIN_FTS_ENTITY_COUNT) {
flowOf(SearchResultUiState.SearchNotReady)
} else {
searchQuery.flatMapLatest { query ->
if (query.length < SEARCH_QUERY_MIN_LENGTH) {
flowOf(SearchResultUiState.EmptyQuery)
} else {
getSearchContentsUseCase(query).asResult().map {
when (it) {
is Result.Success -> {
SearchResultUiState.Success(
topics = it.data.topics,
newsResources = it.data.newsResources,
)
}
is Result.Loading -> {
SearchResultUiState.Loading
}
getSearchContentsCountUseCase()
.flatMapLatest { totalCount ->
if (totalCount < SEARCH_MIN_FTS_ENTITY_COUNT) {
flowOf(SearchResultUiState.SearchNotReady)
} else {
searchQuery.flatMapLatest { query ->
if (query.length < SEARCH_QUERY_MIN_LENGTH) {
flowOf(SearchResultUiState.EmptyQuery)
} else {
getSearchContentsUseCase(query)
.asResult()
.map { result ->
when (result) {
is Result.Success -> SearchResultUiState.Success(
topics = result.data.topics,
newsResources = result.data.newsResources,
)
is Result.Error -> {
SearchResultUiState.LoadFailed
is Result.Loading -> SearchResultUiState.Loading
is Result.Error -> SearchResultUiState.LoadFailed
}
}
}
}
}
}
}
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = SearchResultUiState.Loading,
)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = SearchResultUiState.Loading,
)
val recentSearchQueriesUiState: StateFlow<RecentSearchQueriesUiState> =
recentSearchQueriesUseCase().map(RecentSearchQueriesUiState::Success)
recentSearchQueriesUseCase()
.map(RecentSearchQueriesUiState::Success)
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
@ -107,16 +104,9 @@ class SearchViewModel @Inject constructor(
*/
fun onSearchTriggered(query: String) {
viewModelScope.launch {
recentSearchRepository.insertOrReplaceRecentSearch(query)
recentSearchRepository.insertOrReplaceRecentSearch(searchQuery = query)
}
analyticsHelper.logEvent(
AnalyticsEvent(
type = SEARCH_QUERY,
extras = listOf(
Param(SEARCH_QUERY, query),
),
),
)
analyticsHelper.logEventSearchTriggered(query = query)
}
fun clearRecentSearches() {
@ -126,6 +116,14 @@ class SearchViewModel @Inject constructor(
}
}
private fun AnalyticsHelper.logEventSearchTriggered(query: String) =
logEvent(
event = AnalyticsEvent(
type = SEARCH_QUERY,
extras = listOf(element = Param(key = SEARCH_QUERY, value = query)),
),
)
/** Minimum length where search query is considered as [SearchResultUiState.EmptyQuery] */
private const val SEARCH_QUERY_MIN_LENGTH = 2

Loading…
Cancel
Save