diff --git a/app-nia-catalog/src/main/java/com/google/samples/apps/niacatalog/ui/Catalog.kt b/app-nia-catalog/src/main/java/com/google/samples/apps/niacatalog/ui/Catalog.kt index 52e1c7485..a18600f33 100644 --- a/app-nia-catalog/src/main/java/com/google/samples/apps/niacatalog/ui/Catalog.kt +++ b/app-nia-catalog/src/main/java/com/google/samples/apps/niacatalog/ui/Catalog.kt @@ -38,7 +38,6 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import com.google.accompanist.flowlayout.FlowRow import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaButton -import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaDropdownMenuButton import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaFilterChip import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaIconToggleButton import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaNavigationBar @@ -167,23 +166,6 @@ fun NiaCatalog() { } } item { Text("Dropdown menus", Modifier.padding(top = 16.dp)) } - item { - FlowRow(mainAxisSpacing = 16.dp) { - NiaDropdownMenuButton( - text = { Text("Enabled") }, - items = listOf("Item 1", "Item 2", "Item 3"), - onItemClick = {}, - itemText = { item -> Text(item) }, - ) - NiaDropdownMenuButton( - text = { Text("Disabled") }, - items = listOf("Item 1", "Item 2", "Item 3"), - onItemClick = {}, - itemText = { item -> Text(item) }, - enabled = false, - ) - } - } item { Text("Chips", Modifier.padding(top = 16.dp)) } item { FlowRow(mainAxisSpacing = 16.dp) { @@ -315,45 +297,19 @@ fun NiaCatalog() { item { Text("Tags", Modifier.padding(top = 16.dp)) } item { FlowRow(mainAxisSpacing = 16.dp) { - var expandedTopicId by remember { mutableStateOf(null) } - - var firstFollowed by remember { mutableStateOf(false) } NiaTopicTag( - expanded = expandedTopicId == "Topic 1", - followed = firstFollowed, - onDropdownMenuToggle = { show -> - expandedTopicId = if (show) "Topic 1" else null - }, - onFollowClick = { firstFollowed = true }, - onUnfollowClick = { firstFollowed = false }, - onBrowseClick = {}, + followed = true, + onClick = {}, text = { Text(text = "Topic 1".uppercase()) }, - followText = { Text(text = "Follow") }, - unFollowText = { Text(text = "Unfollow") }, - browseText = { Text(text = "Browse topic") }, ) - var secondFollowed by remember { mutableStateOf(true) } NiaTopicTag( - expanded = expandedTopicId == "Topic 2", - followed = secondFollowed, - onDropdownMenuToggle = { show -> - expandedTopicId = if (show) "Topic 2" else null - }, - onFollowClick = { secondFollowed = true }, - onUnfollowClick = { secondFollowed = false }, - onBrowseClick = {}, + followed = false, + onClick = {}, text = { Text(text = "Topic 2".uppercase()) }, - followText = { Text(text = "Follow") }, - unFollowText = { Text(text = "Unfollow") }, - browseText = { Text(text = "Browse topic") }, ) NiaTopicTag( - expanded = false, followed = false, - onDropdownMenuToggle = {}, - onFollowClick = {}, - onUnfollowClick = {}, - onBrowseClick = {}, + onClick = {}, text = { Text(text = "Disabled".uppercase()) }, enabled = false, ) 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 d6e30a10e..bc950ee92 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 @@ -37,7 +37,6 @@ import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicScreen @Composable fun NiaNavHost( navController: NavHostController, - onBackClick: () -> Unit, modifier: Modifier = Modifier, startDestination: String = forYouNavigationRoute, ) { @@ -46,14 +45,18 @@ fun NiaNavHost( startDestination = startDestination, modifier = modifier, ) { - forYouScreen() - bookmarksScreen() + // TODO: handle topic clicks from each top level destination + forYouScreen(onTopicClick = {}) + bookmarksScreen(onTopicClick = {}) interestsGraph( - navigateToTopic = { topicId -> + onTopicClick = { topicId -> navController.navigateToTopic(topicId) }, nestedGraphs = { - topicScreen(onBackClick) + topicScreen( + onBackClick = navController::popBackStack, + onTopicClick = {}, + ) }, ) } diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaApp.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaApp.kt index 14bc11992..a8d321562 100644 --- a/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaApp.kt +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaApp.kt @@ -178,10 +178,7 @@ fun NiaApp( ) } - NiaNavHost( - navController = appState.navController, - onBackClick = appState::onBackClick, - ) + NiaNavHost(appState.navController) } // TODO: We may want to add padding or spacer when the snackbar is shown so that diff --git a/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt b/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt index 6f929530c..7f655af21 100644 --- a/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt +++ b/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt @@ -136,10 +136,6 @@ class NiaAppState( } } - fun onBackClick() { - navController.popBackStack() - } - fun setShowSettingsDialog(shouldShow: Boolean) { shouldShowSettingsDialog = shouldShow } diff --git a/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/DropdownMenu.kt b/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/DropdownMenu.kt deleted file mode 100644 index b624ebcb6..000000000 --- a/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/DropdownMenu.kt +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.samples.apps.nowinandroid.core.designsystem.component - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.sizeIn -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.DropdownMenu -import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.ProvideTextStyle -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons - -/** - * Now in Android dropdown menu button with included trailing icon as well as text label and item - * content slots. - * - * @param items The list of items to display in the menu. - * @param onItemClick Called when the user clicks on a menu item. - * @param modifier Modifier to be applied to the button. - * @param enabled Controls the enabled state of the button. When `false`, this button will not be - * clickable and will appear disabled to accessibility services. - * @param dismissOnItemClick Whether the menu should be dismissed when an item is clicked. - * @param itemText The text label content for a given item. - * @param itemLeadingIcon The leading icon content for a given item. - * @param itemTrailingIcon The trailing icon content for a given item. - */ -@Composable -fun NiaDropdownMenuButton( - items: List, - onItemClick: (item: T) -> Unit, - modifier: Modifier = Modifier, - enabled: Boolean = true, - dismissOnItemClick: Boolean = true, - text: @Composable () -> Unit, - itemText: @Composable (item: T) -> Unit, - itemLeadingIcon: @Composable ((item: T) -> Unit)? = null, - itemTrailingIcon: @Composable ((item: T) -> Unit)? = null, -) { - var expanded by remember { mutableStateOf(false) } - Box(modifier = modifier) { - OutlinedButton( - onClick = { expanded = true }, - enabled = enabled, - colors = ButtonDefaults.outlinedButtonColors( - contentColor = MaterialTheme.colorScheme.onBackground, - ), - border = BorderStroke( - width = NiaDropdownMenuDefaults.DropdownMenuButtonBorderWidth, - color = if (enabled) { - MaterialTheme.colorScheme.outline - } else { - MaterialTheme.colorScheme.onSurface.copy( - alpha = NiaDropdownMenuDefaults.DisabledDropdownMenuButtonBorderAlpha, - ) - }, - ), - contentPadding = NiaDropdownMenuDefaults.DropdownMenuButtonContentPadding, - ) { - NiaDropdownMenuButtonContent( - text = text, - trailingIcon = { - Icon( - imageVector = if (expanded) { - NiaIcons.ArrowDropUp - } else { - NiaIcons.ArrowDropDown - }, - contentDescription = null, - ) - }, - ) - } - NiaDropdownMenu( - expanded = expanded, - onDismissRequest = { expanded = false }, - items = items, - onItemClick = onItemClick, - dismissOnItemClick = dismissOnItemClick, - itemText = itemText, - itemLeadingIcon = itemLeadingIcon, - itemTrailingIcon = itemTrailingIcon, - ) - } -} - -/** - * Internal Now in Android dropdown menu button content layout for arranging the text label and - * trailing icon. - * - * @param text The button text label content. - * @param trailingIcon The button trailing icon content. Default is `null` for no trailing icon. - */ -@Composable -private fun NiaDropdownMenuButtonContent( - text: @Composable () -> Unit, - trailingIcon: @Composable (() -> Unit)? = null, -) { - Box( - Modifier - .padding( - end = if (trailingIcon != null) { - ButtonDefaults.IconSpacing - } else { - 0.dp - }, - ), - ) { - ProvideTextStyle(value = MaterialTheme.typography.labelSmall) { - text() - } - } - if (trailingIcon != null) { - Box(Modifier.sizeIn(maxHeight = ButtonDefaults.IconSize)) { - trailingIcon() - } - } -} - -/** - * Now in Android dropdown menu with item content slots. Wraps Material 3 [DropdownMenu] and - * [DropdownMenuItem]. - * - * @param expanded Whether the menu is currently open and visible to the user. - * @param onDismissRequest Called when the user requests to dismiss the menu, such as by - * tapping outside the menu's bounds. - * @param items The list of items to display in the menu. - * @param onItemClick Called when the user clicks on a menu item. - * @param dismissOnItemClick Whether the menu should be dismissed when an item is clicked. - * @param itemText The text label content for a given item. - * @param itemLeadingIcon The leading icon content for a given item. - * @param itemTrailingIcon The trailing icon content for a given item. - */ -@Composable -fun NiaDropdownMenu( - expanded: Boolean, - onDismissRequest: () -> Unit, - items: List, - onItemClick: (item: T) -> Unit, - dismissOnItemClick: Boolean = true, - itemText: @Composable (item: T) -> Unit, - itemLeadingIcon: @Composable ((item: T) -> Unit)? = null, - itemTrailingIcon: @Composable ((item: T) -> Unit)? = null, -) { - DropdownMenu( - expanded = expanded, - onDismissRequest = onDismissRequest, - ) { - items.forEach { item -> - DropdownMenuItem( - text = { itemText(item) }, - onClick = { - onItemClick(item) - if (dismissOnItemClick) onDismissRequest() - }, - leadingIcon = if (itemLeadingIcon != null) { - { itemLeadingIcon(item) } - } else { - null - }, - trailingIcon = if (itemTrailingIcon != null) { - { itemTrailingIcon(item) } - } else { - null - }, - ) - } - } -} - -/** - * Now in Android dropdown menu default values. - */ -object NiaDropdownMenuDefaults { - // TODO: File bug - // OutlinedButton border color doesn't respect disabled state by default - const val DisabledDropdownMenuButtonBorderAlpha = 0.12f - - // TODO: File bug - // OutlinedButton default border width isn't exposed via ButtonDefaults - val DropdownMenuButtonBorderWidth = 1.dp - - // TODO: File bug - // Various default button padding values aren't exposed via ButtonDefaults - val DropdownMenuButtonContentPadding = - PaddingValues( - start = 24.dp, - top = 8.dp, - end = 16.dp, - bottom = 8.dp, - ) -} diff --git a/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/Tag.kt b/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/Tag.kt index cf8b246bb..ba8fde1c9 100644 --- a/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/Tag.kt +++ b/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/Tag.kt @@ -20,28 +20,18 @@ import androidx.compose.foundation.layout.Box import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ProvideTextStyle -import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import com.google.samples.apps.nowinandroid.core.designsystem.R @Composable fun NiaTopicTag( modifier: Modifier = Modifier, - expanded: Boolean = false, followed: Boolean, - onDropdownMenuToggle: (show: Boolean) -> Unit = {}, - onFollowClick: () -> Unit, - onUnfollowClick: () -> Unit, - onBrowseClick: () -> Unit, + onClick: () -> Unit, enabled: Boolean = true, text: @Composable () -> Unit, - followText: @Composable () -> Unit = { Text(stringResource(R.string.follow)) }, - unFollowText: @Composable () -> Unit = { Text(stringResource(R.string.unfollow)) }, - browseText: @Composable () -> Unit = { Text(stringResource(R.string.browse_topic)) }, ) { Box(modifier = modifier) { val containerColor = if (followed) { @@ -52,7 +42,7 @@ fun NiaTopicTag( ) } TextButton( - onClick = { onDropdownMenuToggle(true) }, + onClick = onClick, enabled = enabled, colors = ButtonDefaults.textButtonColors( containerColor = containerColor, @@ -66,25 +56,6 @@ fun NiaTopicTag( text() } } - NiaDropdownMenu( - expanded = expanded, - onDismissRequest = { onDropdownMenuToggle(false) }, - items = if (followed) listOf(UNFOLLOW, BROWSE) else listOf(FOLLOW, BROWSE), - onItemClick = { item -> - when (item) { - FOLLOW -> onFollowClick() - UNFOLLOW -> onUnfollowClick() - BROWSE -> onBrowseClick() - } - }, - itemText = { item -> - when (item) { - FOLLOW -> followText() - UNFOLLOW -> unFollowText() - BROWSE -> browseText() - } - }, - ) } } @@ -98,7 +69,3 @@ object NiaTagDefaults { // Button disabled container alpha value not exposed by ButtonDefaults const val DisabledTopicTagContainerAlpha = 0.12f } - -private const val FOLLOW = 1 -private const val UNFOLLOW = 2 -private const val BROWSE = 3 diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml deleted file mode 100644 index 5d1158888..000000000 --- a/core/designsystem/src/main/res/values/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - Follow - Unfollow - Browse topic - diff --git a/core/ui/src/androidTest/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardTest.kt b/core/ui/src/androidTest/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardTest.kt index 927ccfa28..712771422 100644 --- a/core/ui/src/androidTest/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardTest.kt +++ b/core/ui/src/androidTest/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardTest.kt @@ -41,6 +41,7 @@ class NewsResourceCardTest { isBookmarked = false, onToggleBookmark = {}, onClick = {}, + onTopicClick = {}, ) dateFormatted = dateFormatted(publishDate = newsWithKnownResourceType.publishDate) @@ -68,6 +69,7 @@ class NewsResourceCardTest { isBookmarked = false, onToggleBookmark = {}, onClick = {}, + onTopicClick = {}, ) dateFormatted = dateFormatted(publishDate = newsWithUnknownResourceType.publishDate) @@ -81,7 +83,10 @@ class NewsResourceCardTest { @Test fun testTopicsChipColorBackground_matchesFollowedState() { composeTestRule.setContent { - NewsResourceTopics(topics = followableTopicTestData) + NewsResourceTopics( + topics = followableTopicTestData, + onTopicClick = {}, + ) } for (followableTopic in followableTopicTestData) { 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 73c1a21e4..2ad38a26e 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 @@ -47,6 +47,7 @@ import com.google.samples.apps.nowinandroid.core.domain.model.UserNewsResource fun LazyGridScope.newsFeed( feedState: NewsFeedUiState, onNewsResourcesCheckedChanged: (String, Boolean) -> Unit, + onTopicClick: (String) -> Unit, ) { when (feedState) { NewsFeedUiState.Loading -> Unit @@ -68,6 +69,7 @@ fun LazyGridScope.newsFeed( !userNewsResource.isSaved, ) }, + onTopicClick = onTopicClick, ) } } @@ -112,6 +114,7 @@ private fun NewsFeedLoadingPreview() { newsFeed( feedState = NewsFeedUiState.Loading, onNewsResourcesCheckedChanged = { _, _ -> }, + onTopicClick = {}, ) } } @@ -129,6 +132,7 @@ private fun NewsFeedContentPreview( newsFeed( feedState = NewsFeedUiState.Success(userNewsResources), onNewsResourcesCheckedChanged = { _, _ -> }, + onTopicClick = {}, ) } } 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 ae6cadbfa..cffa59436 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 @@ -79,6 +79,7 @@ fun NewsResourceCardExpanded( isBookmarked: Boolean, onToggleBookmark: () -> Unit, onClick: () -> Unit, + onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, ) { val clickActionLabel = stringResource(R.string.card_tap_action) @@ -116,7 +117,10 @@ fun NewsResourceCardExpanded( Spacer(modifier = Modifier.height(12.dp)) NewsResourceShortDescription(userNewsResource.content) Spacer(modifier = Modifier.height(12.dp)) - NewsResourceTopics(userNewsResource.followableTopics) + NewsResourceTopics( + topics = userNewsResource.followableTopics, + onTopicClick = onTopicClick, + ) } } } @@ -231,26 +235,17 @@ fun NewsResourceShortDescription( @Composable fun NewsResourceTopics( topics: List, + onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, ) { - // Store the ID of the Topic which has its "following" menu expanded, if any. - // To avoid UI confusion, only one topic can have an expanded menu at a time. - var expandedTopicId by remember { mutableStateOf(null) } - Row( modifier = modifier.horizontalScroll(rememberScrollState()), // causes narrow chips horizontalArrangement = Arrangement.spacedBy(4.dp), ) { for (followableTopic in topics) { NiaTopicTag( - expanded = expandedTopicId == followableTopic.topic.id, followed = followableTopic.isFollowed, - onDropdownMenuToggle = { show -> - expandedTopicId = if (show) followableTopic.topic.id else null - }, - onFollowClick = { }, // ToDo - onUnfollowClick = { }, // ToDo - onBrowseClick = { }, // ToDo + onClick = { onTopicClick(followableTopic.topic.id) }, text = { val contentDescription = if (followableTopic.isFollowed) { stringResource( @@ -308,6 +303,7 @@ private fun ExpandedNewsResourcePreview( isBookmarked = true, onToggleBookmark = {}, onClick = {}, + onTopicClick = {}, ) } } 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 a63bae657..a2c02f84f 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 @@ -37,6 +37,7 @@ fun LazyListScope.userNewsResourceCardItems( items: List, onToggleBookmark: (item: UserNewsResource) -> Unit, onItemClick: ((item: UserNewsResource) -> Unit)? = null, + onTopicClick: (String) -> Unit, itemModifier: Modifier = Modifier, ) = items( items = items, @@ -56,6 +57,7 @@ fun LazyListScope.userNewsResourceCardItems( else -> onItemClick(userNewsResource) } }, + onTopicClick = onTopicClick, modifier = itemModifier, ) }, diff --git a/feature/bookmarks/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreenTest.kt b/feature/bookmarks/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreenTest.kt index f9faca080..3662bd47f 100644 --- a/feature/bookmarks/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreenTest.kt +++ b/feature/bookmarks/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/bookmarks/BookmarksScreenTest.kt @@ -50,7 +50,8 @@ class BookmarksScreenTest { composeTestRule.setContent { BookmarksScreen( feedState = NewsFeedUiState.Loading, - removeFromBookmarks = { }, + removeFromBookmarks = {}, + onTopicClick = {}, ) } @@ -68,7 +69,8 @@ class BookmarksScreenTest { feedState = NewsFeedUiState.Success( userNewsResourcesTestData.take(2), ), - removeFromBookmarks = { }, + removeFromBookmarks = {}, + onTopicClick = {}, ) } @@ -110,6 +112,7 @@ class BookmarksScreenTest { assertEquals(userNewsResourcesTestData[0].id, newsResourceId) removeFromBookmarksCalled = true }, + onTopicClick = {}, ) } @@ -138,7 +141,8 @@ class BookmarksScreenTest { composeTestRule.setContent { BookmarksScreen( feedState = NewsFeedUiState.Success(emptyList()), - removeFromBookmarks = { }, + removeFromBookmarks = {}, + onTopicClick = {}, ) } 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 1169f5777..5f43fd235 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 @@ -66,6 +66,7 @@ import com.google.samples.apps.nowinandroid.core.ui.newsFeed @OptIn(ExperimentalLifecycleComposeApi::class) @Composable internal fun BookmarksRoute( + onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, viewModel: BookmarksViewModel = hiltViewModel(), ) { @@ -73,6 +74,7 @@ internal fun BookmarksRoute( BookmarksScreen( feedState = feedState, removeFromBookmarks = viewModel::removeFromSavedResources, + onTopicClick = onTopicClick, modifier = modifier, ) } @@ -85,12 +87,13 @@ internal fun BookmarksRoute( internal fun BookmarksScreen( feedState: NewsFeedUiState, removeFromBookmarks: (String) -> Unit, + onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, ) { when (feedState) { Loading -> LoadingState(modifier) is Success -> if (feedState.feed.isNotEmpty()) { - BookmarksGrid(feedState, removeFromBookmarks, modifier) + BookmarksGrid(feedState, removeFromBookmarks, onTopicClick, modifier) } else { EmptyState(modifier) } @@ -112,6 +115,7 @@ private fun LoadingState(modifier: Modifier = Modifier) { private fun BookmarksGrid( feedState: NewsFeedUiState, removeFromBookmarks: (String) -> Unit, + onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, ) { val scrollableState = rememberLazyGridState() @@ -129,6 +133,7 @@ private fun BookmarksGrid( newsFeed( feedState = feedState, onNewsResourcesCheckedChanged = { id, _ -> removeFromBookmarks(id) }, + onTopicClick = onTopicClick, ) item(span = { GridItemSpan(maxLineSpan) }) { Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) @@ -193,6 +198,7 @@ private fun BookmarksGridPreview( BookmarksGrid( feedState = Success(userNewsResources), removeFromBookmarks = {}, + onTopicClick = {}, ) } } 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..eeb7f1576 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(onTopicClick: (String) -> Unit) { composable(route = bookmarksRoute) { - BookmarksRoute() + BookmarksRoute(onTopicClick) } } diff --git a/feature/foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt b/feature/foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt index a6be20013..ab712cbb5 100644 --- a/feature/foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt +++ b/feature/foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt @@ -53,6 +53,7 @@ class ForYouScreenTest { onboardingUiState = OnboardingUiState.Loading, feedState = NewsFeedUiState.Loading, onTopicCheckedChanged = { _, _ -> }, + onTopicClick = {}, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, ) @@ -75,6 +76,7 @@ class ForYouScreenTest { onboardingUiState = OnboardingUiState.NotShown, feedState = NewsFeedUiState.Success(emptyList()), onTopicCheckedChanged = { _, _ -> }, + onTopicClick = {}, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, ) @@ -103,6 +105,7 @@ class ForYouScreenTest { feed = emptyList(), ), onTopicCheckedChanged = { _, _ -> }, + onTopicClick = {}, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, ) @@ -146,6 +149,7 @@ class ForYouScreenTest { feed = emptyList(), ), onTopicCheckedChanged = { _, _ -> }, + onTopicClick = {}, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, ) @@ -182,6 +186,7 @@ class ForYouScreenTest { OnboardingUiState.Shown(topics = followableTopicTestData), feedState = NewsFeedUiState.Loading, onTopicCheckedChanged = { _, _ -> }, + onTopicClick = {}, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, ) @@ -204,6 +209,7 @@ class ForYouScreenTest { onboardingUiState = OnboardingUiState.NotShown, feedState = NewsFeedUiState.Loading, onTopicCheckedChanged = { _, _ -> }, + onTopicClick = {}, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, ) @@ -227,6 +233,7 @@ class ForYouScreenTest { feed = userNewsResourcesTestData, ), onTopicCheckedChanged = { _, _ -> }, + onTopicClick = {}, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, ) 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 492660142..cb0b0ecd6 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 @OptIn(ExperimentalLifecycleComposeApi::class) @Composable internal fun ForYouRoute( + onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, viewModel: ForYouViewModel = hiltViewModel(), ) { @@ -104,6 +105,7 @@ internal fun ForYouRoute( onboardingUiState = onboardingUiState, feedState = feedState, onTopicCheckedChanged = viewModel::updateTopicSelection, + onTopicClick = onTopicClick, saveFollowedTopics = viewModel::dismissOnboarding, onNewsResourcesCheckedChanged = viewModel::updateNewsResourceSaved, modifier = modifier, @@ -116,6 +118,7 @@ internal fun ForYouScreen( onboardingUiState: OnboardingUiState, feedState: NewsFeedUiState, onTopicCheckedChanged: (String, Boolean) -> Unit, + onTopicClick: (String) -> Unit, saveFollowedTopics: () -> Unit, onNewsResourcesCheckedChanged: (String, Boolean) -> Unit, modifier: Modifier = Modifier, @@ -175,6 +178,7 @@ internal fun ForYouScreen( newsFeed( feedState = feedState, onNewsResourcesCheckedChanged = onNewsResourcesCheckedChanged, + onTopicClick = onTopicClick, ) item(span = { GridItemSpan(maxLineSpan) }) { @@ -407,6 +411,7 @@ fun ForYouScreenPopulatedFeed( onTopicCheckedChanged = { _, _ -> }, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, + onTopicClick = {}, ) } } @@ -429,6 +434,7 @@ fun ForYouScreenOfflinePopulatedFeed( onTopicCheckedChanged = { _, _ -> }, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, + onTopicClick = {}, ) } } @@ -453,6 +459,7 @@ fun ForYouScreenTopicSelection( onTopicCheckedChanged = { _, _ -> }, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, + onTopicClick = {}, ) } } @@ -470,6 +477,7 @@ fun ForYouScreenLoading() { onTopicCheckedChanged = { _, _ -> }, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, + onTopicClick = {}, ) } } @@ -492,6 +500,7 @@ fun ForYouScreenPopulatedAndLoading( onTopicCheckedChanged = { _, _ -> }, saveFollowedTopics = {}, onNewsResourcesCheckedChanged = { _, _ -> }, + onTopicClick = {}, ) } } 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..c7dea1e96 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(onTopicClick: (String) -> Unit) { composable(route = forYouNavigationRoute) { - ForYouRoute() + ForYouRoute(onTopicClick) } } diff --git a/feature/interests/src/androidTest/java/com/google/samples/apps/nowinandroid/interests/InterestsScreenTest.kt b/feature/interests/src/androidTest/java/com/google/samples/apps/nowinandroid/interests/InterestsScreenTest.kt index 7f06eee6b..492e91fa3 100644 --- a/feature/interests/src/androidTest/java/com/google/samples/apps/nowinandroid/interests/InterestsScreenTest.kt +++ b/feature/interests/src/androidTest/java/com/google/samples/apps/nowinandroid/interests/InterestsScreenTest.kt @@ -109,7 +109,7 @@ class InterestsScreenTest { InterestsScreen( uiState = uiState, followTopic = { _, _ -> }, - navigateToTopic = {}, + onTopicClick = {}, ) } } diff --git a/feature/interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/InterestsScreen.kt b/feature/interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/InterestsScreen.kt index fd45c7608..ec0179139 100644 --- a/feature/interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/InterestsScreen.kt +++ b/feature/interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/InterestsScreen.kt @@ -37,7 +37,7 @@ import com.google.samples.apps.nowinandroid.core.ui.FollowableTopicPreviewParame @OptIn(ExperimentalLifecycleComposeApi::class) @Composable internal fun InterestsRoute( - navigateToTopic: (String) -> Unit, + onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, viewModel: InterestsViewModel = hiltViewModel(), ) { @@ -46,7 +46,7 @@ internal fun InterestsRoute( InterestsScreen( uiState = uiState, followTopic = viewModel::followTopic, - navigateToTopic = navigateToTopic, + onTopicClick = onTopicClick, modifier = modifier, ) } @@ -55,7 +55,7 @@ internal fun InterestsRoute( internal fun InterestsScreen( uiState: InterestsUiState, followTopic: (String, Boolean) -> Unit, - navigateToTopic: (String) -> Unit, + onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, ) { Column( @@ -71,7 +71,7 @@ internal fun InterestsScreen( is InterestsUiState.Interests -> TopicsTabContent( topics = uiState.topics, - onTopicClick = navigateToTopic, + onTopicClick = onTopicClick, onFollowButtonClick = followTopic, modifier = modifier, ) @@ -98,7 +98,7 @@ fun InterestsScreenPopulated( topics = followableTopics, ), followTopic = { _, _ -> }, - navigateToTopic = {}, + onTopicClick = {}, ) } } @@ -112,7 +112,7 @@ fun InterestsScreenLoading() { InterestsScreen( uiState = InterestsUiState.Loading, followTopic = { _, _ -> }, - navigateToTopic = {}, + onTopicClick = {}, ) } } @@ -126,7 +126,7 @@ fun InterestsScreenEmpty() { InterestsScreen( uiState = InterestsUiState.Empty, followTopic = { _, _ -> }, - navigateToTopic = {}, + onTopicClick = {}, ) } } diff --git a/feature/interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt b/feature/interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt index 9a5ce7696..bef6987f4 100644 --- a/feature/interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt +++ b/feature/interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/navigation/InterestsNavigation.kt @@ -31,7 +31,7 @@ fun NavController.navigateToInterestsGraph(navOptions: NavOptions? = null) { } fun NavGraphBuilder.interestsGraph( - navigateToTopic: (String) -> Unit, + onTopicClick: (String) -> Unit, nestedGraphs: NavGraphBuilder.() -> Unit, ) { navigation( @@ -39,9 +39,7 @@ fun NavGraphBuilder.interestsGraph( startDestination = interestsRoute, ) { composable(route = interestsRoute) { - InterestsRoute( - navigateToTopic = navigateToTopic, - ) + InterestsRoute(onTopicClick) } nestedGraphs() } 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 626b0e773..3a267d7e7 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 @@ -55,8 +55,9 @@ class TopicScreenTest { TopicScreen( topicUiState = TopicUiState.Loading, newsUiState = NewsUiState.Loading, - onBackClick = { }, - onFollowClick = { }, + onBackClick = {}, + onFollowClick = {}, + onTopicClick = {}, onBookmarkChanged = { _, _ -> }, ) } @@ -73,8 +74,9 @@ class TopicScreenTest { TopicScreen( topicUiState = TopicUiState.Success(testTopic), newsUiState = NewsUiState.Loading, - onBackClick = { }, - onFollowClick = { }, + onBackClick = {}, + onFollowClick = {}, + onTopicClick = {}, onBookmarkChanged = { _, _ -> }, ) } @@ -96,8 +98,9 @@ class TopicScreenTest { TopicScreen( topicUiState = TopicUiState.Loading, newsUiState = NewsUiState.Success(userNewsResourcesTestData), - onBackClick = { }, - onFollowClick = { }, + onBackClick = {}, + onFollowClick = {}, + onTopicClick = {}, onBookmarkChanged = { _, _ -> }, ) } @@ -117,8 +120,9 @@ class TopicScreenTest { newsUiState = NewsUiState.Success( userNewsResourcesTestData, ), - onBackClick = { }, - onFollowClick = { }, + onBackClick = {}, + onFollowClick = {}, + onTopicClick = {}, onBookmarkChanged = { _, _ -> }, ) } 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 e7b218072..9d2c3e817 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 @@ -65,6 +65,7 @@ import com.google.samples.apps.nowinandroid.feature.topic.TopicUiState.Loading @Composable internal fun TopicRoute( onBackClick: () -> Unit, + onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, viewModel: TopicViewModel = hiltViewModel(), ) { @@ -78,6 +79,7 @@ internal fun TopicRoute( onBackClick = onBackClick, onFollowClick = viewModel::followTopicToggle, onBookmarkChanged = viewModel::bookmarkNews, + onTopicClick = onTopicClick, ) } @@ -88,6 +90,7 @@ internal fun TopicScreen( newsUiState: NewsUiState, onBackClick: () -> Unit, onFollowClick: (Boolean) -> Unit, + onTopicClick: (String) -> Unit, onBookmarkChanged: (String, Boolean) -> Unit, modifier: Modifier = Modifier, ) { @@ -124,6 +127,7 @@ internal fun TopicScreen( news = newsUiState, imageUrl = topicUiState.followableTopic.topic.imageUrl, onBookmarkChanged = onBookmarkChanged, + onTopicClick = onTopicClick, ) } } @@ -139,13 +143,14 @@ private fun LazyListScope.TopicBody( news: NewsUiState, imageUrl: String, onBookmarkChanged: (String, Boolean) -> Unit, + onTopicClick: (String) -> Unit, ) { // TODO: Show icon if available item { TopicHeader(name, description, imageUrl) } - userNewsResourceCards(news, onBookmarkChanged) + userNewsResourceCards(news, onBookmarkChanged, onTopicClick) } @Composable @@ -176,12 +181,14 @@ private fun TopicHeader(name: String, description: String, imageUrl: String) { private fun LazyListScope.userNewsResourceCards( news: NewsUiState, onBookmarkChanged: (String, Boolean) -> Unit, + onTopicClick: (String) -> Unit, ) { when (news) { is NewsUiState.Success -> { userNewsResourceCardItems( items = news.news, onToggleBookmark = { onBookmarkChanged(it.id, !it.isSaved) }, + onTopicClick = onTopicClick, itemModifier = Modifier.padding(24.dp), ) } @@ -202,11 +209,12 @@ 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 = { _, _ -> }, + onTopicClick = {}, ) } } @@ -263,6 +271,7 @@ fun TopicScreenPopulated( onBackClick = {}, onFollowClick = {}, onBookmarkChanged = { _, _ -> }, + onTopicClick = {}, ) } } @@ -279,6 +288,7 @@ fun TopicScreenLoading() { onBackClick = {}, onFollowClick = {}, onBookmarkChanged = { _, _ -> }, + onTopicClick = {}, ) } } 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 1cc43bbd1..3a21da1c3 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 @@ -42,6 +42,7 @@ fun NavController.navigateToTopic(topicId: String) { fun NavGraphBuilder.topicScreen( onBackClick: () -> Unit, + onTopicClick: (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, onTopicClick = onTopicClick) } } diff --git a/lint/src/main/java/com/google/samples/apps/nowinandroid/lint/designsystem/DesignSystemDetector.kt b/lint/src/main/java/com/google/samples/apps/nowinandroid/lint/designsystem/DesignSystemDetector.kt index 39aa07160..6f4bca0df 100644 --- a/lint/src/main/java/com/google/samples/apps/nowinandroid/lint/designsystem/DesignSystemDetector.kt +++ b/lint/src/main/java/com/google/samples/apps/nowinandroid/lint/designsystem/DesignSystemDetector.kt @@ -85,7 +85,6 @@ class DesignSystemDetector : Detector(), Detector.UastScanner { "TextButton" to "NiaTextButton", "FilterChip" to "NiaFilterChip", "ElevatedFilterChip" to "NiaFilterChip", - "DropdownMenu" to "NiaDropdownMenu", "NavigationBar" to "NiaNavigationBar", "NavigationBarItem" to "NiaNavigationBarItem", "NavigationRail" to "NiaNavigationRail",