Rename Destinations to Routes

Change-Id: Ie9120031fc3738d0640c922624f15db0e15417d7
dt/nav-safe-args-android-dependency
Don Turner 7 months ago
parent 041e46eacf
commit da8f32a2ea

@ -20,7 +20,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.bookmarksScreen import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.bookmarksScreen
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.ForYouDestination import com.google.samples.apps.nowinandroid.feature.foryou.navigation.ForYouRoute
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.forYouScreen import com.google.samples.apps.nowinandroid.feature.foryou.navigation.forYouScreen
import com.google.samples.apps.nowinandroid.feature.interests.navigation.navigateToInterests import com.google.samples.apps.nowinandroid.feature.interests.navigation.navigateToInterests
import com.google.samples.apps.nowinandroid.feature.search.navigation.searchScreen import com.google.samples.apps.nowinandroid.feature.search.navigation.searchScreen
@ -44,7 +44,7 @@ fun NiaNavHost(
val navController = appState.navController val navController = appState.navController
NavHost( NavHost(
navController = navController, navController = navController,
startDestination = ForYouDestination(), startDestination = ForYouRoute(),
modifier = modifier, modifier = modifier,
) { ) {
forYouScreen(onTopicClick = navController::navigateToInterests) forYouScreen(onTopicClick = navController::navigateToInterests)

@ -19,9 +19,9 @@ package com.google.samples.apps.nowinandroid.navigation
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import com.google.samples.apps.nowinandroid.R import com.google.samples.apps.nowinandroid.R
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.BookmarksDestination import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.BookmarksRoute
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.ForYouDestination import com.google.samples.apps.nowinandroid.feature.foryou.navigation.ForYouRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsDestination import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute
import kotlin.reflect.KClass import kotlin.reflect.KClass
import com.google.samples.apps.nowinandroid.feature.bookmarks.R as bookmarksR import com.google.samples.apps.nowinandroid.feature.bookmarks.R as bookmarksR
import com.google.samples.apps.nowinandroid.feature.foryou.R as forYouR import com.google.samples.apps.nowinandroid.feature.foryou.R as forYouR
@ -44,20 +44,20 @@ enum class TopLevelDestination(
unselectedIcon = NiaIcons.UpcomingBorder, unselectedIcon = NiaIcons.UpcomingBorder,
iconTextId = forYouR.string.feature_foryou_title, iconTextId = forYouR.string.feature_foryou_title,
titleTextId = R.string.app_name, titleTextId = R.string.app_name,
route = ForYouDestination::class, route = ForYouRoute::class,
), ),
BOOKMARKS( BOOKMARKS(
selectedIcon = NiaIcons.Bookmarks, selectedIcon = NiaIcons.Bookmarks,
unselectedIcon = NiaIcons.BookmarksBorder, unselectedIcon = NiaIcons.BookmarksBorder,
iconTextId = bookmarksR.string.feature_bookmarks_title, iconTextId = bookmarksR.string.feature_bookmarks_title,
titleTextId = bookmarksR.string.feature_bookmarks_title, titleTextId = bookmarksR.string.feature_bookmarks_title,
route = BookmarksDestination::class, route = BookmarksRoute::class,
), ),
INTERESTS( INTERESTS(
selectedIcon = NiaIcons.Grid3x3, selectedIcon = NiaIcons.Grid3x3,
unselectedIcon = NiaIcons.Grid3x3, unselectedIcon = NiaIcons.Grid3x3,
iconTextId = searchR.string.feature_search_interests, iconTextId = searchR.string.feature_search_interests,
titleTextId = searchR.string.feature_search_interests, titleTextId = searchR.string.feature_search_interests,
route = InterestsDestination::class, route = InterestsRoute::class,
), ),
} }

@ -35,11 +35,11 @@ import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourc
import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor
import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor
import com.google.samples.apps.nowinandroid.core.ui.TrackDisposableJank import com.google.samples.apps.nowinandroid.core.ui.TrackDisposableJank
import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.BookmarksDestination import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.BookmarksRoute
import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.navigateToBookmarks import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.navigateToBookmarks
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.ForYouDestination import com.google.samples.apps.nowinandroid.feature.foryou.navigation.ForYouRoute
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.navigateToForYou import com.google.samples.apps.nowinandroid.feature.foryou.navigation.navigateToForYou
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsDestination import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.navigateToInterests import com.google.samples.apps.nowinandroid.feature.interests.navigation.navigateToInterests
import com.google.samples.apps.nowinandroid.feature.search.navigation.navigateToSearch import com.google.samples.apps.nowinandroid.feature.search.navigation.navigateToSearch
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
@ -99,9 +99,9 @@ class NiaAppState(
val currentTopLevelDestination: TopLevelDestination? val currentTopLevelDestination: TopLevelDestination?
@Composable get() { @Composable get() {
with(currentDestination) { with(currentDestination) {
if (this?.hasRoute<ForYouDestination>() == true) return FOR_YOU if (this?.hasRoute<ForYouRoute>() == true) return FOR_YOU
if (this?.hasRoute<BookmarksDestination>() == true) return BOOKMARKS if (this?.hasRoute<BookmarksRoute>() == true) return BOOKMARKS
if (this?.hasRoute<InterestsDestination>() == true) return INTERESTS if (this?.hasRoute<InterestsRoute>() == true) return INTERESTS
} }
return null return null
} }

@ -19,7 +19,7 @@ package com.google.samples.apps.nowinandroid.ui.interests2pane
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.navigation.toRoute import androidx.navigation.toRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsDestination import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_KEY import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_KEY
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
@ -32,10 +32,10 @@ class Interests2PaneViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle, private val savedStateHandle: SavedStateHandle,
) : ViewModel() { ) : ViewModel() {
val destination = savedStateHandle.toRoute<InterestsDestination>() val route = savedStateHandle.toRoute<InterestsRoute>()
val selectedTopicId: StateFlow<String?> = savedStateHandle.getStateFlow( val selectedTopicId: StateFlow<String?> = savedStateHandle.getStateFlow(
key = TOPIC_ID_KEY, key = TOPIC_ID_KEY,
initialValue = destination.initialTopicId, initialValue = route.initialTopicId,
) )
fun onTopicClick(topicId: String?) { fun onTopicClick(topicId: String?) {

@ -40,20 +40,20 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
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.InterestsDestination import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute
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.TopicDestination import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute
import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic
import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicScreen import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicScreen
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import java.util.UUID import java.util.UUID
@Serializable object TopicPlaceholderDestination @Serializable internal object TopicPlaceholderRoute
@Serializable object DetailPaneNavHostDestination @Serializable internal object DetailPaneNavHostRoute
fun NavGraphBuilder.interestsListDetailScreen() { fun NavGraphBuilder.interestsListDetailScreen() {
composable<InterestsDestination> { composable<InterestsRoute> {
InterestsListDetailScreen() InterestsListDetailScreen()
} }
} }
@ -87,9 +87,9 @@ internal fun InterestsListDetailScreen(
listDetailNavigator.navigateBack() listDetailNavigator.navigateBack()
} }
var nestedNavHostStartDestination by remember { var nestedNavHostStartRoute by remember {
val destination = selectedTopicId?.let { TopicDestination(id = it) } ?: TopicPlaceholderDestination val route = selectedTopicId?.let { TopicRoute(id = it) } ?: TopicPlaceholderRoute
mutableStateOf(destination) mutableStateOf(route)
} }
var nestedNavKey by rememberSaveable( var nestedNavKey by rememberSaveable(
stateSaver = Saver({ it.toString() }, UUID::fromString), stateSaver = Saver({ it.toString() }, UUID::fromString),
@ -106,11 +106,11 @@ internal fun InterestsListDetailScreen(
// If the detail pane was visible, then use the nestedNavController navigate call // If the detail pane was visible, then use the nestedNavController navigate call
// directly // directly
nestedNavController.navigateToTopic(topicId) { nestedNavController.navigateToTopic(topicId) {
popUpTo<DetailPaneNavHostDestination>() popUpTo<DetailPaneNavHostRoute>()
} }
} else { } else {
// Otherwise, recreate the NavHost entirely, and start at the new destination // Otherwise, recreate the NavHost entirely, and start at the new destination
nestedNavHostStartDestination = TopicDestination(id = topicId) nestedNavHostStartRoute = TopicRoute(id = topicId)
nestedNavKey = UUID.randomUUID() nestedNavKey = UUID.randomUUID()
} }
listDetailNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail) listDetailNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail)
@ -132,15 +132,15 @@ internal fun InterestsListDetailScreen(
key(nestedNavKey) { key(nestedNavKey) {
NavHost( NavHost(
navController = nestedNavController, navController = nestedNavController,
startDestination = nestedNavHostStartDestination, startDestination = nestedNavHostStartRoute,
route = DetailPaneNavHostDestination::class, route = DetailPaneNavHostRoute::class,
) { ) {
topicScreen( topicScreen(
showBackButton = !listDetailNavigator.isListPaneVisible(), showBackButton = !listDetailNavigator.isListPaneVisible(),
onBackClick = listDetailNavigator::navigateBack, onBackClick = listDetailNavigator::navigateBack,
onTopicClick = ::onTopicClickShowDetailPane, onTopicClick = ::onTopicClickShowDetailPane,
) )
composable<TopicPlaceholderDestination> { composable<TopicPlaceholderRoute> {
TopicDetailPlaceholder() TopicDetailPlaceholder()
} }
} }

@ -23,16 +23,16 @@ import androidx.navigation.compose.composable
import com.google.samples.apps.nowinandroid.feature.bookmarks.BookmarksRoute import com.google.samples.apps.nowinandroid.feature.bookmarks.BookmarksRoute
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable object BookmarksDestination @Serializable object BookmarksRoute
fun NavController.navigateToBookmarks(navOptions: NavOptions) = fun NavController.navigateToBookmarks(navOptions: NavOptions) =
navigate(route = BookmarksDestination, navOptions) navigate(route = BookmarksRoute, navOptions)
fun NavGraphBuilder.bookmarksScreen( fun NavGraphBuilder.bookmarksScreen(
onTopicClick: (String) -> Unit, onTopicClick: (String) -> Unit,
onShowSnackbar: suspend (String, String?) -> Boolean, onShowSnackbar: suspend (String, String?) -> Boolean,
) { ) {
composable<BookmarksDestination> { composable<BookmarksRoute> {
BookmarksRoute(onTopicClick, onShowSnackbar) BookmarksRoute(onTopicClick, onShowSnackbar)
} }
} }

@ -30,14 +30,14 @@ const val LINKED_NEWS_RESOURCE_ID = "linkedNewsResourceId"
private const val DEEP_LINK_BASE_PATH = "$DEEP_LINK_SCHEME_AND_HOST/$FOR_YOU_PATH" private const val DEEP_LINK_BASE_PATH = "$DEEP_LINK_SCHEME_AND_HOST/$FOR_YOU_PATH"
@Serializable data class ForYouDestination(val linkedNewsResourceId: String? = null) @Serializable data class ForYouRoute(val linkedNewsResourceId: String? = null)
fun NavController.navigateToForYou(navOptions: NavOptions) = navigate(route = ForYouDestination(), navOptions) fun NavController.navigateToForYou(navOptions: NavOptions) = navigate(route = ForYouRoute(), navOptions)
fun NavGraphBuilder.forYouScreen(onTopicClick: (String) -> Unit) { fun NavGraphBuilder.forYouScreen(onTopicClick: (String) -> Unit) {
composable<ForYouDestination>( composable<ForYouRoute>(
deepLinks = listOf( deepLinks = listOf(
navDeepLink<ForYouDestination>(basePath = DEEP_LINK_BASE_PATH), navDeepLink<ForYouRoute>(basePath = DEEP_LINK_BASE_PATH),
), ),
) { ) {
ForYouRoute(onTopicClick) ForYouRoute(onTopicClick)

@ -24,7 +24,7 @@ import com.google.samples.apps.nowinandroid.core.data.repository.UserDataReposit
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.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_KEY import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_KEY
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
@ -41,10 +41,10 @@ class InterestsViewModel @Inject constructor(
getFollowableTopics: GetFollowableTopicsUseCase, getFollowableTopics: GetFollowableTopicsUseCase,
) : ViewModel() { ) : ViewModel() {
private val interestsDestination: InterestsDestination = savedStateHandle.toRoute() private val interestsRoute: InterestsRoute = savedStateHandle.toRoute()
private val selectedTopicId = savedStateHandle.getStateFlow( private val selectedTopicId = savedStateHandle.getStateFlow(
key = TOPIC_ID_KEY, key = TOPIC_ID_KEY,
initialValue = interestsDestination.initialTopicId, initialValue = interestsRoute.initialTopicId,
) )
val uiState: StateFlow<InterestsUiState> = combine( val uiState: StateFlow<InterestsUiState> = combine(

@ -22,7 +22,7 @@ import kotlinx.serialization.Serializable
const val TOPIC_ID_KEY = "topicId" const val TOPIC_ID_KEY = "topicId"
@Serializable data class InterestsDestination( @Serializable data class InterestsRoute(
// The ID of the topic which will be initially selected at this destination // The ID of the topic which will be initially selected at this destination
val initialTopicId: String?, val initialTopicId: String?,
) )
@ -31,5 +31,5 @@ fun NavController.navigateToInterests(
initialTopicId: String? = null, initialTopicId: String? = null,
navOptions: NavOptions? = null, navOptions: NavOptions? = null,
) { ) {
navigate(route = InterestsDestination(initialTopicId), navOptions) navigate(route = InterestsRoute(initialTopicId), navOptions)
} }

@ -26,7 +26,7 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserData
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.feature.interests.InterestsUiState import com.google.samples.apps.nowinandroid.feature.interests.InterestsUiState
import com.google.samples.apps.nowinandroid.feature.interests.InterestsViewModel import com.google.samples.apps.nowinandroid.feature.interests.InterestsViewModel
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsDestination import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.UnconfinedTestDispatcher
@ -59,7 +59,7 @@ class InterestsViewModelTest {
// TODO: This line causes tests to fail since it introduces an Android dependency // TODO: This line causes tests to fail since it introduces an Android dependency
// see b/340966212 for more information // see b/340966212 for more information
savedStateHandle = SavedStateHandle( savedStateHandle = SavedStateHandle(
route = InterestsDestination(initialTopicId = testInputTopics[0].topic.id), route = InterestsRoute(initialTopicId = testInputTopics[0].topic.id),
), ),
userDataRepository = userDataRepository, userDataRepository = userDataRepository,
getFollowableTopics = getFollowableTopicsUseCase, getFollowableTopics = getFollowableTopicsUseCase,

@ -29,7 +29,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
import com.google.samples.apps.nowinandroid.core.result.Result import com.google.samples.apps.nowinandroid.core.result.Result
import com.google.samples.apps.nowinandroid.core.result.asResult import com.google.samples.apps.nowinandroid.core.result.asResult
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicDestination import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
@ -48,7 +48,7 @@ class TopicViewModel @Inject constructor(
userNewsResourceRepository: UserNewsResourceRepository, userNewsResourceRepository: UserNewsResourceRepository,
) : ViewModel() { ) : ViewModel() {
val topicId = savedStateHandle.toRoute<TopicDestination>().id val topicId = savedStateHandle.toRoute<TopicRoute>().id
val topicUiState: StateFlow<TopicUiState> = topicUiState( val topicUiState: StateFlow<TopicUiState> = topicUiState(
topicId = topicId, topicId = topicId,

@ -23,10 +23,10 @@ import androidx.navigation.compose.composable
import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable data class TopicDestination(val id: String) @Serializable data class TopicRoute(val id: String)
fun NavController.navigateToTopic(topicId: String, navOptions: NavOptionsBuilder.() -> Unit = {}) { fun NavController.navigateToTopic(topicId: String, navOptions: NavOptionsBuilder.() -> Unit = {}) {
navigate(route = TopicDestination(topicId)) { navigate(route = TopicRoute(topicId)) {
navOptions() navOptions()
} }
} }
@ -36,7 +36,7 @@ fun NavGraphBuilder.topicScreen(
onBackClick: () -> Unit, onBackClick: () -> Unit,
onTopicClick: (String) -> Unit, onTopicClick: (String) -> Unit,
) { ) {
composable<TopicDestination> { composable<TopicRoute> {
TopicScreen( TopicScreen(
showBackButton = showBackButton, showBackButton = showBackButton,
onBackClick = onBackClick, onBackClick = onBackClick,

Loading…
Cancel
Save