Remove nested scaffold from the bookmarks screen

Change-Id: Ie8b6f160d341156a6f9c02c0ca7f530095fb2950
pull/777/head
Miłosz Moczkowski 2 years ago
parent caaa82b909
commit 7b30720b25

@ -39,6 +39,7 @@ import com.google.samples.apps.nowinandroid.ui.NiaAppState
@Composable @Composable
fun NiaNavHost( fun NiaNavHost(
appState: NiaAppState, appState: NiaAppState,
onShowSnackbar: suspend (String, String?) -> Boolean,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
startDestination: String = forYouNavigationRoute, startDestination: String = forYouNavigationRoute,
) { ) {
@ -50,7 +51,10 @@ fun NiaNavHost(
) { ) {
// TODO: handle topic clicks from each top level destination // TODO: handle topic clicks from each top level destination
forYouScreen(onTopicClick = {}) forYouScreen(onTopicClick = {})
bookmarksScreen(onTopicClick = {}) bookmarksScreen(
onTopicClick = navController::navigateToTopic,
onShowSnackbar = onShowSnackbar,
)
searchScreen( searchScreen(
onBackClick = navController::popBackStack, onBackClick = navController::popBackStack,
onInterestsClick = { appState.navigateToTopLevelDestination(INTERESTS) }, onInterestsClick = { appState.navigateToTopLevelDestination(INTERESTS) },

@ -33,8 +33,10 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarDuration.Indefinite import androidx.compose.material3.SnackbarDuration.Indefinite
import androidx.compose.material3.SnackbarDuration.Short
import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult.ActionPerformed
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.windowsizeclass.WindowSizeClass import androidx.compose.material3.windowsizeclass.WindowSizeClass
@ -195,7 +197,13 @@ fun NiaApp(
) )
} }
NiaNavHost(appState) NiaNavHost(appState = appState, onShowSnackbar = { message, action ->
snackbarHostState.showSnackbar(
message = message,
actionLabel = action,
duration = Short,
) == ActionPerformed
})
} }
// TODO: We may want to add padding or spacer when the snackbar is shown so that // TODO: We may want to add padding or spacer when the snackbar is shown so that

@ -50,6 +50,7 @@ class BookmarksScreenTest {
composeTestRule.setContent { composeTestRule.setContent {
BookmarksScreen( BookmarksScreen(
feedState = NewsFeedUiState.Loading, feedState = NewsFeedUiState.Loading,
onShowSnackbar = { _, _ -> false },
removeFromBookmarks = {}, removeFromBookmarks = {},
onTopicClick = {}, onTopicClick = {},
onNewsResourceViewed = {}, onNewsResourceViewed = {},
@ -70,6 +71,7 @@ class BookmarksScreenTest {
feedState = NewsFeedUiState.Success( feedState = NewsFeedUiState.Success(
userNewsResourcesTestData.take(2), userNewsResourcesTestData.take(2),
), ),
onShowSnackbar = { _, _ -> false },
removeFromBookmarks = {}, removeFromBookmarks = {},
onTopicClick = {}, onTopicClick = {},
onNewsResourceViewed = {}, onNewsResourceViewed = {},
@ -110,6 +112,7 @@ class BookmarksScreenTest {
feedState = NewsFeedUiState.Success( feedState = NewsFeedUiState.Success(
userNewsResourcesTestData.take(2), userNewsResourcesTestData.take(2),
), ),
onShowSnackbar = { _, _ -> false },
removeFromBookmarks = { newsResourceId -> removeFromBookmarks = { newsResourceId ->
assertEquals(userNewsResourcesTestData[0].id, newsResourceId) assertEquals(userNewsResourcesTestData[0].id, newsResourceId)
removeFromBookmarksCalled = true removeFromBookmarksCalled = true
@ -144,6 +147,7 @@ class BookmarksScreenTest {
composeTestRule.setContent { composeTestRule.setContent {
BookmarksScreen( BookmarksScreen(
feedState = NewsFeedUiState.Success(emptyList()), feedState = NewsFeedUiState.Success(emptyList()),
onShowSnackbar = { _, _ -> false },
removeFromBookmarks = {}, removeFromBookmarks = {},
onTopicClick = {}, onTopicClick = {},
onNewsResourceViewed = {}, onNewsResourceViewed = {},

@ -19,7 +19,6 @@ package com.google.samples.apps.nowinandroid.feature.bookmarks
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@ -35,19 +34,12 @@ import androidx.compose.foundation.lazy.grid.GridCells.Adaptive
import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarDuration.Short
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult.ActionPerformed
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.ColorFilter
@ -79,12 +71,14 @@ import com.google.samples.apps.nowinandroid.core.ui.newsFeed
@Composable @Composable
internal fun BookmarksRoute( internal fun BookmarksRoute(
onTopicClick: (String) -> Unit, onTopicClick: (String) -> Unit,
onShowSnackbar: suspend (String, String?) -> Boolean,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
viewModel: BookmarksViewModel = hiltViewModel(), viewModel: BookmarksViewModel = hiltViewModel(),
) { ) {
val feedState by viewModel.feedUiState.collectAsStateWithLifecycle() val feedState by viewModel.feedUiState.collectAsStateWithLifecycle()
BookmarksScreen( BookmarksScreen(
feedState = feedState, feedState = feedState,
onShowSnackbar = onShowSnackbar,
removeFromBookmarks = viewModel::removeFromSavedResources, removeFromBookmarks = viewModel::removeFromSavedResources,
onNewsResourceViewed = { viewModel.setNewsResourceViewed(it, true) }, onNewsResourceViewed = { viewModel.setNewsResourceViewed(it, true) },
onTopicClick = onTopicClick, onTopicClick = onTopicClick,
@ -98,11 +92,11 @@ internal fun BookmarksRoute(
/** /**
* Displays the user's bookmarked articles. Includes support for loading and empty states. * Displays the user's bookmarked articles. Includes support for loading and empty states.
*/ */
@OptIn(ExperimentalMaterial3Api::class)
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
@Composable @Composable
internal fun BookmarksScreen( internal fun BookmarksScreen(
feedState: NewsFeedUiState, feedState: NewsFeedUiState,
onShowSnackbar: suspend (String, String?) -> Boolean,
removeFromBookmarks: (String) -> Unit, removeFromBookmarks: (String) -> Unit,
onNewsResourceViewed: (String) -> Unit, onNewsResourceViewed: (String) -> Unit,
onTopicClick: (String) -> Unit, onTopicClick: (String) -> Unit,
@ -113,18 +107,14 @@ internal fun BookmarksScreen(
) { ) {
val bookmarkRemovedMessage = stringResource(id = R.string.bookmark_removed) val bookmarkRemovedMessage = stringResource(id = R.string.bookmark_removed)
val undoText = stringResource(id = R.string.undo) val undoText = stringResource(id = R.string.undo)
val snackbarHostState = remember { SnackbarHostState() }
LaunchedEffect(shouldDisplayUndoBookmark) { LaunchedEffect(shouldDisplayUndoBookmark) {
if (shouldDisplayUndoBookmark) { if (shouldDisplayUndoBookmark) {
val snackBarResult = snackbarHostState.showSnackbar( val snackBarResult = onShowSnackbar(bookmarkRemovedMessage, undoText)
message = bookmarkRemovedMessage, if (snackBarResult) {
actionLabel = undoText, undoBookmarkRemoval()
duration = Short, } else {
) clearUndoState()
when (snackBarResult) {
ActionPerformed -> { undoBookmarkRemoval() }
else -> { clearUndoState() }
} }
} }
} }
@ -140,20 +130,21 @@ internal fun BookmarksScreen(
onDispose { lifecycleOwner.lifecycle.removeObserver(observer) } onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
} }
Scaffold(snackbarHost = { SnackbarHost(hostState = snackbarHostState) }) { when (feedState) {
Box( Loading -> LoadingState(modifier)
modifier = Modifier.padding(it).fillMaxSize(), is Success -> if (feedState.feed.isNotEmpty()) {
) { BookmarksGrid(
when (feedState) { feedState,
Loading -> LoadingState(modifier) removeFromBookmarks,
is Success -> if (feedState.feed.isNotEmpty()) { onNewsResourceViewed,
BookmarksGrid(feedState, removeFromBookmarks, onNewsResourceViewed, onTopicClick, modifier) onTopicClick,
} else { modifier,
EmptyState(modifier) )
} } else {
} EmptyState(modifier)
} }
} }
TrackScreenViewEvent(screenName = "Saved") TrackScreenViewEvent(screenName = "Saved")
} }

@ -28,8 +28,11 @@ fun NavController.navigateToBookmarks(navOptions: NavOptions? = null) {
this.navigate(bookmarksRoute, navOptions) this.navigate(bookmarksRoute, navOptions)
} }
fun NavGraphBuilder.bookmarksScreen(onTopicClick: (String) -> Unit) { fun NavGraphBuilder.bookmarksScreen(
onTopicClick: (String) -> Unit,
onShowSnackbar: suspend (String, String?) -> Boolean,
) {
composable(route = bookmarksRoute) { composable(route = bookmarksRoute) {
BookmarksRoute(onTopicClick) BookmarksRoute(onTopicClick, onShowSnackbar)
} }
} }

Loading…
Cancel
Save