|
|
|
@ -66,6 +66,7 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopAp
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.designsystem.icon.Icon.DrawableResourceIcon
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.designsystem.icon.Icon.ImageVectorIcon
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalGradientColors
|
|
|
|
|
import com.google.samples.apps.nowinandroid.feature.settings.R as settingsR
|
|
|
|
|
import com.google.samples.apps.nowinandroid.feature.settings.SettingsDialog
|
|
|
|
|
import com.google.samples.apps.nowinandroid.navigation.NiaNavHost
|
|
|
|
@ -86,109 +87,119 @@ fun NiaApp(
|
|
|
|
|
windowSizeClass = windowSizeClass
|
|
|
|
|
),
|
|
|
|
|
) {
|
|
|
|
|
val background: @Composable (@Composable () -> Unit) -> Unit =
|
|
|
|
|
when (appState.currentTopLevelDestination) {
|
|
|
|
|
TopLevelDestination.FOR_YOU -> {
|
|
|
|
|
content ->
|
|
|
|
|
NiaGradientBackground(content = content)
|
|
|
|
|
}
|
|
|
|
|
else -> { content -> NiaBackground(content = content) }
|
|
|
|
|
}
|
|
|
|
|
val showGradientBackground = appState.currentTopLevelDestination == TopLevelDestination.FOR_YOU
|
|
|
|
|
|
|
|
|
|
background {
|
|
|
|
|
NiaBackground {
|
|
|
|
|
NiaGradientBackground(
|
|
|
|
|
topColor = if (showGradientBackground) {
|
|
|
|
|
LocalGradientColors.current.top
|
|
|
|
|
} else {
|
|
|
|
|
Color.Unspecified
|
|
|
|
|
},
|
|
|
|
|
bottomColor = if (showGradientBackground) {
|
|
|
|
|
LocalGradientColors.current.bottom
|
|
|
|
|
} else {
|
|
|
|
|
Color.Unspecified
|
|
|
|
|
},
|
|
|
|
|
containerColor = if (showGradientBackground) {
|
|
|
|
|
LocalGradientColors.current.container
|
|
|
|
|
} else {
|
|
|
|
|
Color.Unspecified
|
|
|
|
|
},
|
|
|
|
|
) {
|
|
|
|
|
val snackbarHostState = remember { SnackbarHostState() }
|
|
|
|
|
|
|
|
|
|
val snackbarHostState = remember { SnackbarHostState() }
|
|
|
|
|
Scaffold(
|
|
|
|
|
modifier = Modifier.semantics {
|
|
|
|
|
testTagsAsResourceId = true
|
|
|
|
|
},
|
|
|
|
|
containerColor = Color.Transparent,
|
|
|
|
|
contentColor = MaterialTheme.colorScheme.onBackground,
|
|
|
|
|
contentWindowInsets = WindowInsets(0, 0, 0, 0),
|
|
|
|
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
|
|
|
|
topBar = {
|
|
|
|
|
// Show the top app bar on top level destinations.
|
|
|
|
|
val destination = appState.currentTopLevelDestination
|
|
|
|
|
if (destination != null) {
|
|
|
|
|
NiaTopAppBar(
|
|
|
|
|
// When the nav rail is displayed, the top app bar will, by default
|
|
|
|
|
// overlap it. This means that the top most item in the nav rail
|
|
|
|
|
// won't be tappable. A workaround is to position the top app bar
|
|
|
|
|
// behind the nav rail using zIndex.
|
|
|
|
|
modifier = Modifier.zIndex(-1F),
|
|
|
|
|
titleRes = destination.titleTextId,
|
|
|
|
|
actionIcon = NiaIcons.Settings,
|
|
|
|
|
actionIconContentDescription = stringResource(
|
|
|
|
|
id = settingsR.string.top_app_bar_action_icon_description
|
|
|
|
|
),
|
|
|
|
|
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
|
|
|
|
containerColor = Color.Transparent
|
|
|
|
|
),
|
|
|
|
|
onActionClick = { appState.setShowSettingsDialog(true) }
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
bottomBar = {
|
|
|
|
|
if (appState.shouldShowBottomBar) {
|
|
|
|
|
NiaBottomBar(
|
|
|
|
|
destinations = appState.topLevelDestinations,
|
|
|
|
|
onNavigateToDestination = appState::navigateToTopLevelDestination,
|
|
|
|
|
currentDestination = appState.currentDestination,
|
|
|
|
|
modifier = Modifier.testTag("NiaBottomBar")
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
) { padding ->
|
|
|
|
|
|
|
|
|
|
Scaffold(
|
|
|
|
|
modifier = Modifier.semantics {
|
|
|
|
|
testTagsAsResourceId = true
|
|
|
|
|
},
|
|
|
|
|
containerColor = Color.Transparent,
|
|
|
|
|
contentColor = MaterialTheme.colorScheme.onBackground,
|
|
|
|
|
contentWindowInsets = WindowInsets(0, 0, 0, 0),
|
|
|
|
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
|
|
|
|
topBar = {
|
|
|
|
|
// Show the top app bar on top level destinations.
|
|
|
|
|
val destination = appState.currentTopLevelDestination
|
|
|
|
|
if (destination != null) {
|
|
|
|
|
NiaTopAppBar(
|
|
|
|
|
// When the nav rail is displayed, the top app bar will, by default
|
|
|
|
|
// overlap it. This means that the top most item in the nav rail
|
|
|
|
|
// won't be tappable. A workaround is to position the top app bar
|
|
|
|
|
// behind the nav rail using zIndex.
|
|
|
|
|
modifier = Modifier.zIndex(-1F),
|
|
|
|
|
titleRes = destination.titleTextId,
|
|
|
|
|
actionIcon = NiaIcons.Settings,
|
|
|
|
|
actionIconContentDescription = stringResource(
|
|
|
|
|
id = settingsR.string.top_app_bar_action_icon_description
|
|
|
|
|
),
|
|
|
|
|
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
|
|
|
|
containerColor = Color.Transparent
|
|
|
|
|
),
|
|
|
|
|
onActionClick = { appState.setShowSettingsDialog(true) }
|
|
|
|
|
val isOffline by appState.isOffline.collectAsStateWithLifecycle()
|
|
|
|
|
|
|
|
|
|
// If user is not connected to the internet show a snack bar to inform them.
|
|
|
|
|
val notConnected = stringResource(R.string.not_connected)
|
|
|
|
|
LaunchedEffect(isOffline) {
|
|
|
|
|
if (isOffline) snackbarHostState.showSnackbar(
|
|
|
|
|
message = notConnected,
|
|
|
|
|
duration = Indefinite
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
bottomBar = {
|
|
|
|
|
if (appState.shouldShowBottomBar) {
|
|
|
|
|
NiaBottomBar(
|
|
|
|
|
destinations = appState.topLevelDestinations,
|
|
|
|
|
onNavigateToDestination = appState::navigateToTopLevelDestination,
|
|
|
|
|
currentDestination = appState.currentDestination,
|
|
|
|
|
modifier = Modifier.testTag("NiaBottomBar")
|
|
|
|
|
|
|
|
|
|
if (appState.shouldShowSettingsDialog) {
|
|
|
|
|
SettingsDialog(
|
|
|
|
|
onDismiss = { appState.setShowSettingsDialog(false) }
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
) { padding ->
|
|
|
|
|
|
|
|
|
|
val isOffline by appState.isOffline.collectAsStateWithLifecycle()
|
|
|
|
|
|
|
|
|
|
// If user is not connected to the internet show a snack bar to inform them.
|
|
|
|
|
val notConnected = stringResource(R.string.not_connected)
|
|
|
|
|
LaunchedEffect(isOffline) {
|
|
|
|
|
if (isOffline) snackbarHostState.showSnackbar(
|
|
|
|
|
message = notConnected,
|
|
|
|
|
duration = Indefinite
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
Row(
|
|
|
|
|
Modifier
|
|
|
|
|
.fillMaxSize()
|
|
|
|
|
.windowInsetsPadding(
|
|
|
|
|
WindowInsets.safeDrawing.only(
|
|
|
|
|
WindowInsetsSides.Horizontal
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
if (appState.shouldShowNavRail) {
|
|
|
|
|
NiaNavRail(
|
|
|
|
|
destinations = appState.topLevelDestinations,
|
|
|
|
|
onNavigateToDestination = appState::navigateToTopLevelDestination,
|
|
|
|
|
currentDestination = appState.currentDestination,
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.testTag("NiaNavRail")
|
|
|
|
|
.safeDrawingPadding()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (appState.shouldShowSettingsDialog) {
|
|
|
|
|
SettingsDialog(
|
|
|
|
|
onDismiss = { appState.setShowSettingsDialog(false) }
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
NiaNavHost(
|
|
|
|
|
navController = appState.navController,
|
|
|
|
|
onBackClick = appState::onBackClick,
|
|
|
|
|
|
|
|
|
|
Row(
|
|
|
|
|
Modifier
|
|
|
|
|
.fillMaxSize()
|
|
|
|
|
.windowInsetsPadding(
|
|
|
|
|
WindowInsets.safeDrawing.only(
|
|
|
|
|
WindowInsetsSides.Horizontal
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
if (appState.shouldShowNavRail) {
|
|
|
|
|
NiaNavRail(
|
|
|
|
|
destinations = appState.topLevelDestinations,
|
|
|
|
|
onNavigateToDestination = appState::navigateToTopLevelDestination,
|
|
|
|
|
currentDestination = appState.currentDestination,
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.testTag("NiaNavRail")
|
|
|
|
|
.safeDrawingPadding()
|
|
|
|
|
.padding(padding)
|
|
|
|
|
.consumedWindowInsets(padding)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NiaNavHost(
|
|
|
|
|
navController = appState.navController,
|
|
|
|
|
onBackClick = appState::onBackClick,
|
|
|
|
|
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.padding(padding)
|
|
|
|
|
.consumedWindowInsets(padding)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// TODO: We may want to add padding or spacer when the snackbar is shown so that
|
|
|
|
|
// content doesn't display behind it.
|
|
|
|
|
// TODO: We may want to add padding or spacer when the snackbar is shown so that
|
|
|
|
|
// content doesn't display behind it.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|