Update to alpha08, use toRoute to obtain destination inside VM

Change-Id: I72f617c594b5e0ae272cf94d2d7288446153420a
dt/nav-safe-args
Don Turner 2 months ago
parent d96bcf8ffe
commit 490997281a

@ -36,6 +36,7 @@ import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.INTERESTS_ROUTE import com.google.samples.apps.nowinandroid.feature.interests.navigation.INTERESTS_ROUTE
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsDestination
import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_ARG import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_ARG
import com.google.samples.apps.nowinandroid.feature.topic.TopicDetailPlaceholder import com.google.samples.apps.nowinandroid.feature.topic.TopicDetailPlaceholder
import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic
@ -47,16 +48,7 @@ import kotlinx.serialization.Serializable
@Serializable object DetailPaneNavHostDestination @Serializable object DetailPaneNavHostDestination
fun NavGraphBuilder.interestsListDetailScreen() { fun NavGraphBuilder.interestsListDetailScreen() {
composable( composable<InterestsDestination>{
route = INTERESTS_ROUTE,
arguments = listOf(
navArgument(TOPIC_ID_ARG) {
type = NavType.StringType
defaultValue = null
nullable = true
},
),
) {
InterestsListDetailScreen() InterestsListDetailScreen()
} }
} }

@ -46,10 +46,7 @@ fun InterestsRoute(
InterestsScreen( InterestsScreen(
uiState = uiState, uiState = uiState,
followTopic = viewModel::followTopic, followTopic = viewModel::followTopic,
onTopicClick = { onTopicClick = onTopicClick,
viewModel.onTopicClick(it)
onTopicClick(it)
},
highlightSelectedTopic = highlightSelectedTopic, highlightSelectedTopic = highlightSelectedTopic,
modifier = modifier, modifier = modifier,
) )

@ -19,47 +19,44 @@ package com.google.samples.apps.nowinandroid.feature.interests
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.navigation.toRoute
import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
import com.google.samples.apps.nowinandroid.core.domain.GetFollowableTopicsUseCase import com.google.samples.apps.nowinandroid.core.domain.GetFollowableTopicsUseCase
import com.google.samples.apps.nowinandroid.core.domain.TopicSortField import com.google.samples.apps.nowinandroid.core.domain.TopicSortField
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsDestination
import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_ARG import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_ARG
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class InterestsViewModel @Inject constructor( class InterestsViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle, savedStateHandle: SavedStateHandle,
val userDataRepository: UserDataRepository, val userDataRepository: UserDataRepository,
getFollowableTopics: GetFollowableTopicsUseCase, getFollowableTopics: GetFollowableTopicsUseCase,
) : ViewModel() { ) : ViewModel() {
val selectedTopicId: StateFlow<String?> = savedStateHandle.getStateFlow(TOPIC_ID_ARG, null) private val interestsDestination : InterestsDestination = savedStateHandle.toRoute()
val uiState: StateFlow<InterestsUiState> = combine( val uiState: StateFlow<InterestsUiState> =
selectedTopicId, getFollowableTopics(sortBy = TopicSortField.NAME).map { topics ->
getFollowableTopics(sortBy = TopicSortField.NAME), InterestsUiState.Interests(interestsDestination.topicId, topics)
InterestsUiState::Interests, }.stateIn(
).stateIn( scope = viewModelScope,
scope = viewModelScope, started = SharingStarted.WhileSubscribed(5_000),
started = SharingStarted.WhileSubscribed(5_000), initialValue = InterestsUiState.Loading,
initialValue = InterestsUiState.Loading, )
)
fun followTopic(followedTopicId: String, followed: Boolean) { fun followTopic(followedTopicId: String, followed: Boolean) {
viewModelScope.launch { viewModelScope.launch {
userDataRepository.setTopicIdFollowed(followedTopicId, followed) userDataRepository.setTopicIdFollowed(followedTopicId, followed)
} }
} }
fun onTopicClick(topicId: String?) {
savedStateHandle[TOPIC_ID_ARG] = topicId
}
} }
sealed interface InterestsUiState { sealed interface InterestsUiState {

@ -23,12 +23,15 @@ import androidx.navigation.NavType
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute
import kotlinx.serialization.Serializable
const val TOPIC_ID_ARG = "topicId" const val TOPIC_ID_ARG = "topicId"
const val INTERESTS_ROUTE_BASE = "interests_route" const val INTERESTS_ROUTE_BASE = "interests_route"
const val INTERESTS_ROUTE = "$INTERESTS_ROUTE_BASE?$TOPIC_ID_ARG={$TOPIC_ID_ARG}" const val INTERESTS_ROUTE = "$INTERESTS_ROUTE_BASE?$TOPIC_ID_ARG={$TOPIC_ID_ARG}"
fun NavController.navigateToInterests(topicId: String? = null, navOptions: NavOptions? = null) { @Serializable data class InterestsDestination(val topicId: String?)
fun NavController.navigateToInterestsOld(topicId: String? = null, navOptions: NavOptions? = null) {
val route = if (topicId != null) { val route = if (topicId != null) {
"${INTERESTS_ROUTE_BASE}?${TOPIC_ID_ARG}=$topicId" "${INTERESTS_ROUTE_BASE}?${TOPIC_ID_ARG}=$topicId"
} else { } else {
@ -37,7 +40,12 @@ fun NavController.navigateToInterests(topicId: String? = null, navOptions: NavOp
navigate(route, navOptions) navigate(route, navOptions)
} }
fun NavGraphBuilder.interestsScreen( fun NavController.navigateToInterests(topicId: String? = null, navOptions: NavOptions? = null) {
navigate(route = InterestsDestination(topicId), navOptions)
}
/*fun NavGraphBuilder.interestsScreenOld(
onTopicClick: (String) -> Unit, onTopicClick: (String) -> Unit,
) { ) {
composable( composable(
@ -52,4 +60,6 @@ fun NavGraphBuilder.interestsScreen(
) { ) {
InterestsRoute(onTopicClick = onTopicClick) InterestsRoute(onTopicClick = onTopicClick)
} }
} }*/

@ -19,6 +19,7 @@ package com.google.samples.apps.nowinandroid.feature.topic
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.navigation.toRoute
import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
@ -47,9 +48,7 @@ class TopicViewModel @Inject constructor(
userNewsResourceRepository: UserNewsResourceRepository, userNewsResourceRepository: UserNewsResourceRepository,
) : ViewModel() { ) : ViewModel() {
// TODO: Remove when alpha08 is released private val topicDestination : TopicDestination = savedStateHandle.toRoute()
private val topicDestination = TopicDestination(savedStateHandle["id"]!!)
//private val topicDestination : TopicDestination = savedStateHandle.toRoute()
val topicId = topicDestination.id val topicId = topicDestination.id

@ -21,7 +21,7 @@ androidxLifecycle = "2.7.0"
androidxMacroBenchmark = "1.2.2" androidxMacroBenchmark = "1.2.2"
androidxMetrics = "1.0.0-alpha04" androidxMetrics = "1.0.0-alpha04"
#androidxNavigation = "2.8.0-SNAPSHOT" #androidxNavigation = "2.8.0-SNAPSHOT"
androidxNavigation = "2.8.0-alpha07" androidxNavigation = "2.8.0-alpha08"
androidxProfileinstaller = "1.3.1" androidxProfileinstaller = "1.3.1"
androidxTestCore = "1.5.0" androidxTestCore = "1.5.0"
androidxTestExt = "1.1.5" androidxTestExt = "1.1.5"

Loading…
Cancel
Save