diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt index 10fafddd9..4c64998e9 100644 --- a/app/src/main/java/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/navigation/NiaNavHost.kt @@ -48,8 +48,16 @@ fun NiaNavHost( startDestination = startDestination, modifier = modifier, ) { - forYouScreen() - bookmarksScreen() + forYouScreen( + navigateToTopic = { topicId -> + navController.navigateToTopic(topicId) + } + ) + bookmarksScreen( + navigateToTopic = { topicId -> + navController.navigateToTopic(topicId) + } + ) interestsGraph( navigateToTopic = { topicId -> navController.navigateToTopic(topicId) @@ -58,8 +66,18 @@ fun NiaNavHost( navController.navigateToAuthor(authorId) }, nestedGraphs = { - topicScreen(onBackClick) - authorScreen(onBackClick) + topicScreen( + onBackClick = onBackClick, + navigateToTopic = { topicId -> + navController.navigateToTopic(topicId) + } + ) + authorScreen( + onBackClick = onBackClick, + navigateToTopic = { topicId -> + navController.navigateToTopic(topicId) + } + ) } ) } diff --git a/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt b/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt index 32308bd63..c220bfc3a 100644 --- a/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt +++ b/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt @@ -42,7 +42,10 @@ import com.google.samples.apps.nowinandroid.core.model.data.previewNewsResources */ fun LazyGridScope.newsFeed( feedState: NewsFeedUiState, - onNewsResourcesCheckedChanged: (String, Boolean) -> Unit + onNewsResourcesCheckedChanged: (String, Boolean) -> Unit, + onFollowTopic: (String) -> Unit, + onUnfollowTopic: (String) -> Unit, + onBrowseTopic: (String) -> Unit, ) { when (feedState) { NewsFeedUiState.Loading -> Unit @@ -63,7 +66,10 @@ fun LazyGridScope.newsFeed( saveableNewsResource.newsResource.id, !saveableNewsResource.isSaved ) - } + }, + onBrowseTopic = onBrowseTopic, + onFollowTopic = onFollowTopic, + onUnfollowTopic = onUnfollowTopic ) } } @@ -97,7 +103,10 @@ fun NewsFeedLoadingPreview() { LazyVerticalGrid(columns = GridCells.Adaptive(300.dp)) { newsFeed( feedState = NewsFeedUiState.Loading, - onNewsResourcesCheckedChanged = { _, _ -> } + onNewsResourcesCheckedChanged = { _, _ -> }, + onBrowseTopic = {}, + onFollowTopic = {}, + onUnfollowTopic = {} ) } } @@ -118,7 +127,10 @@ fun NewsFeedContentPreview() { ) } ), - onNewsResourcesCheckedChanged = { _, _ -> } + onNewsResourcesCheckedChanged = { _, _ -> }, + onBrowseTopic = {}, + onFollowTopic = {}, + onUnfollowTopic = {} ) } } diff --git a/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt b/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt index 16e86c192..bc5e333a3 100644 --- a/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt +++ b/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt @@ -57,7 +57,6 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import coil.compose.AsyncImage -import com.google.samples.apps.nowinandroid.core.designsystem.R as DesignsystemR import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaToggleButton import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopicTag import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons @@ -66,11 +65,12 @@ import com.google.samples.apps.nowinandroid.core.model.data.Author import com.google.samples.apps.nowinandroid.core.model.data.NewsResource import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.previewNewsResources +import kotlinx.datetime.Instant +import kotlinx.datetime.toJavaInstant import java.time.ZoneId import java.time.format.DateTimeFormatter import java.util.Locale -import kotlinx.datetime.Instant -import kotlinx.datetime.toJavaInstant +import com.google.samples.apps.nowinandroid.core.designsystem.R as DesignsystemR /** * [NewsResource] card used on the following screens: For You, Saved @@ -83,6 +83,9 @@ fun NewsResourceCardExpanded( isBookmarked: Boolean, onToggleBookmark: () -> Unit, onClick: () -> Unit, + onFollowTopic: (String) -> Unit, + onUnfollowTopic: (String) -> Unit, + onBrowseTopic: (String) -> Unit, modifier: Modifier = Modifier ) { val clickActionLabel = stringResource(R.string.card_tap_action) @@ -123,7 +126,12 @@ fun NewsResourceCardExpanded( Spacer(modifier = Modifier.height(12.dp)) NewsResourceShortDescription(newsResource.content) Spacer(modifier = Modifier.height(12.dp)) - NewsResourceTopics(newsResource.topics) + NewsResourceTopics( + topics = newsResource.topics, + onBrowseClick = onBrowseTopic, + onFollowClick = onFollowTopic, + onUnfollowClick = onUnfollowTopic + ) } } } @@ -267,6 +275,9 @@ fun NewsResourceShortDescription( @Composable fun NewsResourceTopics( topics: List, + onFollowClick: (String) -> Unit, + onUnfollowClick: (String) -> Unit, + onBrowseClick: (String) -> Unit, modifier: Modifier = Modifier ) { // Store the ID of the Topic which has its "following" menu expanded, if any. @@ -284,9 +295,9 @@ fun NewsResourceTopics( onDropMenuToggle = { show -> expandedTopicId = if (show) topic.id else null }, - onFollowClick = { }, // ToDo - onUnfollowClick = { }, // ToDo - onBrowseClick = { }, // ToDo + onFollowClick = { onFollowClick(topic.id) }, + onUnfollowClick = { onUnfollowClick(topic.id) }, + onBrowseClick = { onBrowseClick(topic.id) }, text = { Text(text = topic.name.uppercase(Locale.getDefault())) } ) } @@ -322,7 +333,10 @@ fun ExpandedNewsResourcePreview() { newsResource = previewNewsResources[0], isBookmarked = true, onToggleBookmark = {}, - onClick = {} + onClick = {}, + onBrowseTopic = {}, + onFollowTopic = {}, + onUnfollowTopic = {} ) } } diff --git a/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardList.kt b/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardList.kt index 25a7bd2dc..37096e2af 100644 --- a/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardList.kt +++ b/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardList.kt @@ -40,6 +40,9 @@ fun LazyListScope.newsResourceCardItems( newsResourceMapper: (item: T) -> NewsResource, isBookmarkedMapper: (item: T) -> Boolean, onToggleBookmark: (item: T) -> Unit, + onFollowTopic: (String) -> Unit, + onUnfollowTopic: (String) -> Unit, + onBrowseTopic: (String) -> Unit, onItemClick: ((item: T) -> Unit)? = null, itemModifier: Modifier = Modifier, ) = items( @@ -55,6 +58,9 @@ fun LazyListScope.newsResourceCardItems( newsResource = newsResource, isBookmarked = isBookmarkedMapper(item), onToggleBookmark = { onToggleBookmark(item) }, + onBrowseTopic = onBrowseTopic, + onFollowTopic = onFollowTopic, + onUnfollowTopic = onUnfollowTopic, onClick = { when (onItemClick) { null -> ContextCompat.startActivity(context, launchResourceIntent, null) diff --git a/feature/author/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/author/AuthorScreenTest.kt b/feature/author/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/author/AuthorScreenTest.kt index b955912f2..438ef7cf7 100644 --- a/feature/author/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/author/AuthorScreenTest.kt +++ b/feature/author/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/author/AuthorScreenTest.kt @@ -58,6 +58,9 @@ class AuthorScreenTest { onBackClick = { }, onFollowClick = { }, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } @@ -76,6 +79,9 @@ class AuthorScreenTest { onBackClick = { }, onFollowClick = { }, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } @@ -106,6 +112,9 @@ class AuthorScreenTest { onBackClick = { }, onFollowClick = { }, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } @@ -132,6 +141,9 @@ class AuthorScreenTest { onBackClick = { }, onFollowClick = { }, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } diff --git a/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorScreen.kt b/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorScreen.kt index 114b4c438..2fc629a3c 100644 --- a/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorScreen.kt +++ b/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorScreen.kt @@ -67,6 +67,7 @@ import com.google.samples.apps.nowinandroid.core.ui.newsResourceCardItems @Composable internal fun AuthorRoute( onBackClick: () -> Unit, + navigateToTopic: (String) -> Unit, modifier: Modifier = Modifier, viewModel: AuthorViewModel = hiltViewModel(), ) { @@ -80,6 +81,13 @@ internal fun AuthorRoute( onBackClick = onBackClick, onFollowClick = viewModel::followAuthorToggle, onBookmarkChanged = viewModel::bookmarkNews, + onBrowseTopic = navigateToTopic, + onFollowTopic = { topicId -> + viewModel.followTopic(topicId, true) + }, + onUnfollowTopic = { topicId -> + viewModel.followTopic(topicId, false) + }, ) } @@ -91,6 +99,9 @@ internal fun AuthorScreen( onBackClick: () -> Unit, onFollowClick: (Boolean) -> Unit, onBookmarkChanged: (String, Boolean) -> Unit, + onFollowTopic: (String) -> Unit, + onUnfollowTopic: (String) -> Unit, + onBrowseTopic: (String) -> Unit, modifier: Modifier = Modifier, ) { val scrollableState = rememberLazyListState() @@ -127,6 +138,9 @@ internal fun AuthorScreen( author = authorUiState.followableAuthor.author, news = newsUiState, onBookmarkChanged = onBookmarkChanged, + onBrowseTopic = onBrowseTopic, + onFollowTopic = onFollowTopic, + onUnfollowTopic = onUnfollowTopic ) } } @@ -139,13 +153,22 @@ internal fun AuthorScreen( private fun LazyListScope.authorBody( author: Author, news: NewsUiState, - onBookmarkChanged: (String, Boolean) -> Unit + onBookmarkChanged: (String, Boolean) -> Unit, + onFollowTopic: (String) -> Unit, + onUnfollowTopic: (String) -> Unit, + onBrowseTopic: (String) -> Unit, ) { item { AuthorHeader(author) } - authorCards(news, onBookmarkChanged) + authorCards( + news = news, + onBookmarkChanged = onBookmarkChanged, + onBrowseTopic = onBrowseTopic, + onFollowTopic = onFollowTopic, + onUnfollowTopic = onUnfollowTopic + ) } @Composable @@ -176,7 +199,10 @@ private fun AuthorHeader(author: Author) { private fun LazyListScope.authorCards( news: NewsUiState, - onBookmarkChanged: (String, Boolean) -> Unit + onBookmarkChanged: (String, Boolean) -> Unit, + onFollowTopic: (String) -> Unit, + onUnfollowTopic: (String) -> Unit, + onBrowseTopic: (String) -> Unit, ) { when (news) { is NewsUiState.Success -> { @@ -185,6 +211,9 @@ private fun LazyListScope.authorCards( newsResourceMapper = { it.newsResource }, isBookmarkedMapper = { it.isSaved }, onToggleBookmark = { onBookmarkChanged(it.newsResource.id, !it.isSaved) }, + onBrowseTopic = onBrowseTopic, + onFollowTopic = onFollowTopic, + onUnfollowTopic = onUnfollowTopic, itemModifier = Modifier.padding(24.dp) ) } @@ -252,6 +281,9 @@ fun AuthorScreenPopulated() { onBackClick = {}, onFollowClick = {}, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } } @@ -268,6 +300,9 @@ fun AuthorScreenLoading() { onBackClick = {}, onFollowClick = {}, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } } diff --git a/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModel.kt b/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModel.kt index 2f63dbc11..1dba9aa3b 100644 --- a/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModel.kt +++ b/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModel.kt @@ -80,6 +80,12 @@ class AuthorViewModel @Inject constructor( userDataRepository.updateNewsResourceBookmark(newsResourceId, bookmarked) } } + + fun followTopic(followedTopicId: String, followed: Boolean) { + viewModelScope.launch { + userDataRepository.toggleFollowedTopicId(followedTopicId, followed) + } + } } private fun authorUiStateStream( diff --git a/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/navigation/AuthorNavigation.kt b/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/navigation/AuthorNavigation.kt index 59b68ce91..d2b4b21b0 100644 --- a/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/navigation/AuthorNavigation.kt +++ b/feature/author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/navigation/AuthorNavigation.kt @@ -41,7 +41,8 @@ fun NavController.navigateToAuthor(authorId: String) { } fun NavGraphBuilder.authorScreen( - onBackClick: () -> Unit + onBackClick: () -> Unit, + navigateToTopic: (String) -> Unit, ) { composable( route = "author_route/{$authorIdArg}", @@ -49,6 +50,6 @@ fun NavGraphBuilder.authorScreen( navArgument(authorIdArg) { type = NavType.StringType } ) ) { - AuthorRoute(onBackClick = onBackClick) + AuthorRoute(onBackClick = onBackClick, navigateToTopic = navigateToTopic) } } diff --git a/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt b/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt index 560378370..f97162f84 100644 --- a/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt +++ b/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreen.kt @@ -51,13 +51,15 @@ import com.google.samples.apps.nowinandroid.core.ui.newsFeed @Composable internal fun BookmarksRoute( modifier: Modifier = Modifier, + navigateToTopic: (String) -> Unit, viewModel: BookmarksViewModel = hiltViewModel() ) { val feedState by viewModel.feedUiState.collectAsStateWithLifecycle() BookmarksScreen( feedState = feedState, removeFromBookmarks = viewModel::removeFromSavedResources, - modifier = modifier + modifier = modifier, + onBrowseTopic = navigateToTopic, ) } @@ -65,6 +67,7 @@ internal fun BookmarksRoute( fun BookmarksScreen( feedState: NewsFeedUiState, removeFromBookmarks: (String) -> Unit, + onBrowseTopic: (String) -> Unit, modifier: Modifier = Modifier ) { val scrollableState = rememberLazyGridState() @@ -98,6 +101,7 @@ fun BookmarksScreen( newsFeed( feedState = feedState, onNewsResourcesCheckedChanged = { id, _ -> removeFromBookmarks(id) }, + onBrowseTopic = onBrowseTopic, ) item(span = { GridItemSpan(maxLineSpan) }) { Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) diff --git a/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksViewModel.kt b/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksViewModel.kt index 1b9efc6aa..4782d4ec1 100644 --- a/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksViewModel.kt +++ b/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksViewModel.kt @@ -55,4 +55,10 @@ class BookmarksViewModel @Inject constructor( userDataRepository.updateNewsResourceBookmark(newsResourceId, false) } } + + fun followTopic(followedTopicId: String, followed: Boolean) { + viewModelScope.launch { + userDataRepository.toggleFollowedTopicId(followedTopicId, followed) + } + } } diff --git a/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt b/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt index 188c948e4..87a9e5aab 100644 --- a/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt +++ b/feature/bookmarks/src/main/java/com/google/samples/apps/nowinandroid/feature/bookmarks/navigation/BookmarksNavigation.kt @@ -28,8 +28,8 @@ fun NavController.navigateToBookmarks(navOptions: NavOptions? = null) { this.navigate(bookmarksRoute, navOptions) } -fun NavGraphBuilder.bookmarksScreen() { +fun NavGraphBuilder.bookmarksScreen(navigateToTopic: (String) -> Unit) { composable(route = bookmarksRoute) { - BookmarksRoute() + BookmarksRoute(navigateToTopic = navigateToTopic) } } diff --git a/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt b/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt index 4651e1204..c1a9a9c2b 100644 --- a/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt +++ b/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt @@ -92,6 +92,7 @@ import com.google.samples.apps.nowinandroid.core.ui.newsFeed @Composable internal fun ForYouRoute( modifier: Modifier = Modifier, + navigateToTopic: (String) -> Unit, viewModel: ForYouViewModel = hiltViewModel() ) { val onboardingUiState by viewModel.onboardingUiState.collectAsStateWithLifecycle() @@ -106,6 +107,13 @@ internal fun ForYouRoute( onAuthorCheckedChanged = viewModel::updateAuthorSelection, saveFollowedTopics = viewModel::dismissOnboarding, onNewsResourcesCheckedChanged = viewModel::updateNewsResourceSaved, + onBrowseTopic = navigateToTopic, + onFollowTopic = { topicId -> + viewModel.followTopic(topicId, true) + }, + onUnfollowTopic = { topicId -> + viewModel.followTopic(topicId, false) + }, modifier = modifier ) } @@ -119,6 +127,9 @@ internal fun ForYouScreen( onAuthorCheckedChanged: (String, Boolean) -> Unit, saveFollowedTopics: () -> Unit, onNewsResourcesCheckedChanged: (String, Boolean) -> Unit, + onFollowTopic: (String) -> Unit, + onUnfollowTopic: (String) -> Unit, + onBrowseTopic: (String) -> Unit, modifier: Modifier = Modifier, ) { @@ -178,6 +189,9 @@ internal fun ForYouScreen( newsFeed( feedState = feedState, onNewsResourcesCheckedChanged = onNewsResourcesCheckedChanged, + onBrowseTopic = onBrowseTopic, + onFollowTopic = onFollowTopic, + onUnfollowTopic = onUnfollowTopic ) item(span = { GridItemSpan(maxLineSpan) }) { @@ -405,7 +419,10 @@ fun ForYouScreenPopulatedFeed() { onTopicCheckedChanged = { _, _ -> }, onAuthorCheckedChanged = { _, _ -> }, saveFollowedTopics = {}, - onNewsResourcesCheckedChanged = { _, _ -> } + onNewsResourcesCheckedChanged = { _, _ -> }, + onBrowseTopic = {}, + onFollowTopic = {}, + onUnfollowTopic = {} ) } } @@ -427,7 +444,10 @@ fun ForYouScreenOfflinePopulatedFeed() { onTopicCheckedChanged = { _, _ -> }, onAuthorCheckedChanged = { _, _ -> }, saveFollowedTopics = {}, - onNewsResourcesCheckedChanged = { _, _ -> } + onNewsResourcesCheckedChanged = { _, _ -> }, + onBrowseTopic = {}, + onFollowTopic = {}, + onUnfollowTopic = {} ) } } @@ -452,7 +472,10 @@ fun ForYouScreenTopicSelection() { onTopicCheckedChanged = { _, _ -> }, onAuthorCheckedChanged = { _, _ -> }, saveFollowedTopics = {}, - onNewsResourcesCheckedChanged = { _, _ -> } + onNewsResourcesCheckedChanged = { _, _ -> }, + onBrowseTopic = {}, + onFollowTopic = {}, + onUnfollowTopic = {} ) } } @@ -470,7 +493,10 @@ fun ForYouScreenLoading() { onTopicCheckedChanged = { _, _ -> }, onAuthorCheckedChanged = { _, _ -> }, saveFollowedTopics = {}, - onNewsResourcesCheckedChanged = { _, _ -> } + onNewsResourcesCheckedChanged = { _, _ -> }, + onBrowseTopic = {}, + onFollowTopic = {}, + onUnfollowTopic = {} ) } } @@ -492,7 +518,10 @@ fun ForYouScreenPopulatedAndLoading() { onTopicCheckedChanged = { _, _ -> }, onAuthorCheckedChanged = { _, _ -> }, saveFollowedTopics = {}, - onNewsResourcesCheckedChanged = { _, _ -> } + onNewsResourcesCheckedChanged = { _, _ -> }, + onBrowseTopic = {}, + onFollowTopic = {}, + onUnfollowTopic = {} ) } } diff --git a/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt b/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt index 599bfd868..3fd1c25eb 100644 --- a/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt +++ b/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt @@ -129,6 +129,12 @@ class ForYouViewModel @Inject constructor( userDataRepository.setShouldHideOnboarding(true) } } + + fun followTopic(followedTopicId: String, followed: Boolean) { + viewModelScope.launch { + userDataRepository.toggleFollowedTopicId(followedTopicId, followed) + } + } } private fun Flow>.mapToFeedState(): Flow = diff --git a/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt b/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt index f57deab90..9c3daaee2 100644 --- a/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt +++ b/feature/foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/navigation/ForYouNavigation.kt @@ -28,8 +28,8 @@ fun NavController.navigateToForYou(navOptions: NavOptions? = null) { this.navigate(forYouNavigationRoute, navOptions) } -fun NavGraphBuilder.forYouScreen() { +fun NavGraphBuilder.forYouScreen(navigateToTopic: (String) -> Unit,) { composable(route = forYouNavigationRoute) { - ForYouRoute() + ForYouRoute(navigateToTopic = navigateToTopic) } } diff --git a/feature/topic/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/topic/TopicScreenTest.kt b/feature/topic/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/topic/TopicScreenTest.kt index 0f20a5e5e..b78cecf7e 100644 --- a/feature/topic/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/topic/TopicScreenTest.kt +++ b/feature/topic/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/topic/TopicScreenTest.kt @@ -62,6 +62,9 @@ class TopicScreenTest { onBackClick = { }, onFollowClick = { }, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } @@ -80,6 +83,9 @@ class TopicScreenTest { onBackClick = { }, onFollowClick = { }, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } @@ -110,6 +116,9 @@ class TopicScreenTest { onBackClick = { }, onFollowClick = { }, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } @@ -136,6 +145,9 @@ class TopicScreenTest { onBackClick = { }, onFollowClick = { }, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } diff --git a/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicScreen.kt b/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicScreen.kt index 58c572ade..434aff9a8 100644 --- a/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicScreen.kt +++ b/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicScreen.kt @@ -66,6 +66,7 @@ import com.google.samples.apps.nowinandroid.feature.topic.TopicUiState.Loading @Composable internal fun TopicRoute( onBackClick: () -> Unit, + navigateToTopic: (String) -> Unit, modifier: Modifier = Modifier, viewModel: TopicViewModel = hiltViewModel(), ) { @@ -79,6 +80,15 @@ internal fun TopicRoute( onBackClick = onBackClick, onFollowClick = viewModel::followTopicToggle, onBookmarkChanged = viewModel::bookmarkNews, + onBrowseTopic = navigateToTopic, + onFollowTopic = { topicId -> + viewModel.followTopic(topicId, true) + + }, + onUnfollowTopic = { topicId -> + viewModel.followTopic(topicId, false) + + }, ) } @@ -90,6 +100,9 @@ internal fun TopicScreen( onBackClick: () -> Unit, onFollowClick: (Boolean) -> Unit, onBookmarkChanged: (String, Boolean) -> Unit, + onBrowseTopic: (String) -> Unit, + onFollowTopic: (String) -> Unit, + onUnfollowTopic: (String) -> Unit, modifier: Modifier = Modifier, ) { val state = rememberLazyListState() @@ -123,7 +136,10 @@ internal fun TopicScreen( description = topicUiState.followableTopic.topic.longDescription, news = newsUiState, imageUrl = topicUiState.followableTopic.topic.imageUrl, - onBookmarkChanged = onBookmarkChanged + onBookmarkChanged = onBookmarkChanged, + onBrowseTopic = onBrowseTopic, + onFollowTopic = onFollowTopic, + onUnfollowTopic = onUnfollowTopic, ) } } @@ -138,14 +154,23 @@ private fun LazyListScope.TopicBody( description: String, news: NewsUiState, imageUrl: String, - onBookmarkChanged: (String, Boolean) -> Unit + onBookmarkChanged: (String, Boolean) -> Unit, + onBrowseTopic: (String) -> Unit, + onFollowTopic: (String) -> Unit, + onUnfollowTopic: (String) -> Unit, ) { // TODO: Show icon if available item { TopicHeader(name, description, imageUrl) } - TopicCards(news, onBookmarkChanged) + TopicCards( + news = news, + onBookmarkChanged = onBookmarkChanged, + onBrowseTopic = onBrowseTopic, + onFollowTopic = onFollowTopic, + onUnfollowTopic = onUnfollowTopic, + ) } @Composable @@ -174,7 +199,10 @@ private fun TopicHeader(name: String, description: String, imageUrl: String) { private fun LazyListScope.TopicCards( news: NewsUiState, - onBookmarkChanged: (String, Boolean) -> Unit + onBookmarkChanged: (String, Boolean) -> Unit, + onBrowseTopic: (String) -> Unit, + onFollowTopic: (String) -> Unit, + onUnfollowTopic: (String) -> Unit, ) { when (news) { is NewsUiState.Success -> { @@ -183,6 +211,9 @@ private fun LazyListScope.TopicCards( newsResourceMapper = { it.newsResource }, isBookmarkedMapper = { it.isSaved }, onToggleBookmark = { onBookmarkChanged(it.newsResource.id, !it.isSaved) }, + onBrowseTopic = onBrowseTopic, + onFollowTopic = onFollowTopic, + onUnfollowTopic = onUnfollowTopic, itemModifier = Modifier.padding(24.dp) ) } @@ -201,8 +232,14 @@ private fun TopicBodyPreview() { NiaTheme { LazyColumn { TopicBody( - "Jetpack Compose", "Lorem ipsum maximum", - NewsUiState.Success(emptyList()), "", { _, _ -> } + name = "Jetpack Compose", + description = "Lorem ipsum maximum", + news = NewsUiState.Success(emptyList()), + imageUrl = "", + onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } } @@ -263,6 +300,9 @@ fun TopicScreenPopulated() { onBackClick = {}, onFollowClick = {}, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } } @@ -279,6 +319,9 @@ fun TopicScreenLoading() { onBackClick = {}, onFollowClick = {}, onBookmarkChanged = { _, _ -> }, + onBrowseTopic = { }, + onFollowTopic = { }, + onUnfollowTopic = { }, ) } } diff --git a/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt b/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt index 160bcfb3b..79d8853e6 100644 --- a/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt +++ b/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt @@ -79,6 +79,12 @@ class TopicViewModel @Inject constructor( } } + fun followTopic(followedTopicId: String, followed: Boolean) { + viewModelScope.launch { + userDataRepository.toggleFollowedTopicId(followedTopicId, followed) + } + } + fun bookmarkNews(newsResourceId: String, bookmarked: Boolean) { viewModelScope.launch { userDataRepository.updateNewsResourceBookmark(newsResourceId, bookmarked) diff --git a/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt b/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt index 808143275..a0f4b2680 100644 --- a/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt +++ b/feature/topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt @@ -41,7 +41,8 @@ fun NavController.navigateToTopic(topicId: String) { } fun NavGraphBuilder.topicScreen( - onBackClick: () -> Unit + onBackClick: () -> Unit, + navigateToTopic: (String) -> Unit, ) { composable( route = "topic_route/{$topicIdArg}", @@ -49,6 +50,6 @@ fun NavGraphBuilder.topicScreen( navArgument(topicIdArg) { type = NavType.StringType } ) ) { - TopicRoute(onBackClick = onBackClick) + TopicRoute(onBackClick = onBackClick, navigateToTopic = navigateToTopic) } }