diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt index 141c86916..f878c003b 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt @@ -44,7 +44,7 @@ fun NiaNavHost( val navController = appState.navController NavHost( navController = navController, - startDestination = ForYouRoute(), + startDestination = ForYouRoute, modifier = modifier, ) { forYouScreen(onTopicClick = navController::navigateToInterests) diff --git a/core/notifications/src/main/kotlin/com/google/samples/apps/nowinandroid/core/notifications/SystemTrayNotifier.kt b/core/notifications/src/main/kotlin/com/google/samples/apps/nowinandroid/core/notifications/SystemTrayNotifier.kt index 731ac7657..3fc8114dd 100644 --- a/core/notifications/src/main/kotlin/com/google/samples/apps/nowinandroid/core/notifications/SystemTrayNotifier.kt +++ b/core/notifications/src/main/kotlin/com/google/samples/apps/nowinandroid/core/notifications/SystemTrayNotifier.kt @@ -43,8 +43,11 @@ private const val NEWS_NOTIFICATION_REQUEST_CODE = 0 private const val NEWS_NOTIFICATION_SUMMARY_ID = 1 private const val NEWS_NOTIFICATION_CHANNEL_ID = "" private const val NEWS_NOTIFICATION_GROUP = "NEWS_NOTIFICATIONS" -const val DEEP_LINK_SCHEME_AND_HOST = "https://www.nowinandroid.apps.samples.google.com" -const val FOR_YOU_PATH = "foryou" +private const val DEEP_LINK_SCHEME_AND_HOST = "https://www.nowinandroid.apps.samples.google.com" +private const val DEEP_LINK_FOR_YOU_PATH = "foryou" +private const val DEEP_LINK_BASE_PATH = "$DEEP_LINK_SCHEME_AND_HOST/$DEEP_LINK_FOR_YOU_PATH" +const val DEEP_LINK_NEWS_RESOURCE_ID_KEY = "linkedNewsResourceId" +const val DEEP_LINK_URI_PATTERN = "$DEEP_LINK_BASE_PATH/{$DEEP_LINK_NEWS_RESOURCE_ID_KEY}" /** * Implementation of [Notifier] that displays notifications in the system tray. @@ -161,4 +164,4 @@ private fun Context.newsPendingIntent( PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) -private fun NewsResource.newsDeepLinkUri() = "$DEEP_LINK_SCHEME_AND_HOST/$FOR_YOU_PATH/$id".toUri() +private fun NewsResource.newsDeepLinkUri() = "$DEEP_LINK_BASE_PATH/$id".toUri() diff --git a/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt b/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt index 85035a77a..4b6cd39c9 100644 --- a/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt +++ b/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt @@ -27,8 +27,8 @@ import com.google.samples.apps.nowinandroid.core.data.repository.UserDataReposit import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository import com.google.samples.apps.nowinandroid.core.data.util.SyncManager import com.google.samples.apps.nowinandroid.core.domain.GetFollowableTopicsUseCase +import com.google.samples.apps.nowinandroid.core.notifications.DEEP_LINK_NEWS_RESOURCE_ID_KEY import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState -import com.google.samples.apps.nowinandroid.feature.foryou.navigation.LINKED_NEWS_RESOURCE_ID import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted @@ -55,7 +55,7 @@ class ForYouViewModel @Inject constructor( userDataRepository.userData.map { !it.shouldHideOnboarding } val deepLinkedNewsResource = savedStateHandle.getStateFlow( - key = LINKED_NEWS_RESOURCE_ID, + key = DEEP_LINK_NEWS_RESOURCE_ID_KEY, null, ) .flatMapLatest { newsResourceId -> @@ -129,7 +129,7 @@ class ForYouViewModel @Inject constructor( fun onDeepLinkOpened(newsResourceId: String) { if (newsResourceId == deepLinkedNewsResource.value?.id) { - savedStateHandle[LINKED_NEWS_RESOURCE_ID] = null + savedStateHandle[DEEP_LINK_NEWS_RESOURCE_ID_KEY] = null } analyticsHelper.logNewsDeepLinkOpen(newsResourceId = newsResourceId) viewModelScope.launch { @@ -153,7 +153,7 @@ private fun AnalyticsHelper.logNewsDeepLinkOpen(newsResourceId: String) = type = "news_deep_link_opened", extras = listOf( Param( - key = LINKED_NEWS_RESOURCE_ID, + key = DEEP_LINK_NEWS_RESOURCE_ID_KEY, value = newsResourceId, ), ), diff --git a/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt b/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt index fb0f2b82b..5cc83422d 100644 --- a/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt +++ b/feature/foryou/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt @@ -21,23 +21,27 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable import androidx.navigation.navDeepLink -import com.google.samples.apps.nowinandroid.core.notifications.DEEP_LINK_SCHEME_AND_HOST -import com.google.samples.apps.nowinandroid.core.notifications.FOR_YOU_PATH +import com.google.samples.apps.nowinandroid.core.notifications.DEEP_LINK_URI_PATTERN import com.google.samples.apps.nowinandroid.feature.foryou.ForYouScreen import kotlinx.serialization.Serializable -const val LINKED_NEWS_RESOURCE_ID = "linkedNewsResourceId" +@Serializable data object ForYouRoute -private const val DEEP_LINK_BASE_PATH = "$DEEP_LINK_SCHEME_AND_HOST/$FOR_YOU_PATH" - -@Serializable data class ForYouRoute(val linkedNewsResourceId: String? = null) - -fun NavController.navigateToForYou(navOptions: NavOptions) = navigate(route = ForYouRoute(), navOptions) +fun NavController.navigateToForYou(navOptions: NavOptions) = navigate(route = ForYouRoute, navOptions) fun NavGraphBuilder.forYouScreen(onTopicClick: (String) -> Unit) { composable( deepLinks = listOf( - navDeepLink(basePath = DEEP_LINK_BASE_PATH), + navDeepLink { + /** + * This destination has a deep link that enables a specific news resource to be + * opened from a notification (@see SystemTrayNotifier for more). The news resource + * ID is sent in the URI rather than being modelled in the route type because it's + * transient data (stored in SavedStateHandle) that is cleared after the user has + * opened the news resource. + */ + uriPattern = DEEP_LINK_URI_PATTERN + } ), ) { ForYouScreen(onTopicClick)