|
|
@ -16,6 +16,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
package com.google.samples.apps.nowinandroid.ui
|
|
|
|
package com.google.samples.apps.nowinandroid.ui
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import androidx.compose.foundation.layout.Column
|
|
|
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
|
|
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
|
|
|
import androidx.compose.foundation.layout.Row
|
|
|
|
import androidx.compose.foundation.layout.Row
|
|
|
|
import androidx.compose.foundation.layout.WindowInsets
|
|
|
|
import androidx.compose.foundation.layout.WindowInsets
|
|
|
@ -49,7 +50,6 @@ import androidx.compose.ui.res.painterResource
|
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
|
import androidx.compose.ui.semantics.semantics
|
|
|
|
import androidx.compose.ui.semantics.semantics
|
|
|
|
import androidx.compose.ui.semantics.testTagsAsResourceId
|
|
|
|
import androidx.compose.ui.semantics.testTagsAsResourceId
|
|
|
|
import androidx.compose.ui.zIndex
|
|
|
|
|
|
|
|
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
|
|
|
|
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
|
|
|
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
|
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
|
|
import androidx.navigation.NavDestination
|
|
|
|
import androidx.navigation.NavDestination
|
|
|
@ -96,9 +96,25 @@ fun NiaApp(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
background {
|
|
|
|
background {
|
|
|
|
|
|
|
|
|
|
|
|
val snackbarHostState = remember { SnackbarHostState() }
|
|
|
|
val snackbarHostState = remember { SnackbarHostState() }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val isOffline by appState.isOffline.collectAsStateWithLifecycle()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If user is not connected to the internet show a snack bar to inform them.
|
|
|
|
|
|
|
|
val notConnectedMessage = stringResource(R.string.not_connected)
|
|
|
|
|
|
|
|
LaunchedEffect(isOffline) {
|
|
|
|
|
|
|
|
if (isOffline) snackbarHostState.showSnackbar(
|
|
|
|
|
|
|
|
message = notConnectedMessage,
|
|
|
|
|
|
|
|
duration = Indefinite
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (appState.shouldShowSettingsDialog) {
|
|
|
|
|
|
|
|
SettingsDialog(
|
|
|
|
|
|
|
|
onDismiss = { appState.setShowSettingsDialog(false) }
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Scaffold(
|
|
|
|
Scaffold(
|
|
|
|
modifier = Modifier.semantics {
|
|
|
|
modifier = Modifier.semantics {
|
|
|
|
testTagsAsResourceId = true
|
|
|
|
testTagsAsResourceId = true
|
|
|
@ -107,28 +123,6 @@ fun NiaApp(
|
|
|
|
contentColor = MaterialTheme.colorScheme.onBackground,
|
|
|
|
contentColor = MaterialTheme.colorScheme.onBackground,
|
|
|
|
contentWindowInsets = WindowInsets(0, 0, 0, 0),
|
|
|
|
contentWindowInsets = WindowInsets(0, 0, 0, 0),
|
|
|
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
|
|
|
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 = {
|
|
|
|
bottomBar = {
|
|
|
|
if (appState.shouldShowBottomBar) {
|
|
|
|
if (appState.shouldShowBottomBar) {
|
|
|
|
NiaBottomBar(
|
|
|
|
NiaBottomBar(
|
|
|
@ -140,27 +134,11 @@ fun NiaApp(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
) { padding ->
|
|
|
|
) { 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
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (appState.shouldShowSettingsDialog) {
|
|
|
|
|
|
|
|
SettingsDialog(
|
|
|
|
|
|
|
|
onDismiss = { appState.setShowSettingsDialog(false) }
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Row(
|
|
|
|
Row(
|
|
|
|
Modifier
|
|
|
|
Modifier
|
|
|
|
.fillMaxSize()
|
|
|
|
.fillMaxSize()
|
|
|
|
|
|
|
|
.padding(padding)
|
|
|
|
|
|
|
|
.consumedWindowInsets(padding)
|
|
|
|
.windowInsetsPadding(
|
|
|
|
.windowInsetsPadding(
|
|
|
|
WindowInsets.safeDrawing.only(
|
|
|
|
WindowInsets.safeDrawing.only(
|
|
|
|
WindowInsetsSides.Horizontal
|
|
|
|
WindowInsetsSides.Horizontal
|
|
|
@ -178,14 +156,28 @@ fun NiaApp(
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Column(Modifier.fillMaxSize()) {
|
|
|
|
|
|
|
|
// Show the top app bar on top level destinations.
|
|
|
|
|
|
|
|
val destination = appState.currentTopLevelDestination
|
|
|
|
|
|
|
|
if (destination != null) {
|
|
|
|
|
|
|
|
NiaTopAppBar(
|
|
|
|
|
|
|
|
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) }
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NiaNavHost(
|
|
|
|
NiaNavHost(
|
|
|
|
navController = appState.navController,
|
|
|
|
navController = appState.navController,
|
|
|
|
onBackClick = appState::onBackClick,
|
|
|
|
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
|
|
|
|
// TODO: We may want to add padding or spacer when the snackbar is shown so that
|
|
|
|
// content doesn't display behind it.
|
|
|
|
// content doesn't display behind it.
|
|
|
|