StateMessages displayed in Snackbar

Including offline mesage in snackbar-bound state messages
pull/1789/head
TM 9 months ago
parent eb75ebb330
commit cb34888251

@ -16,6 +16,7 @@
package com.google.samples.apps.nowinandroid.ui package com.google.samples.apps.nowinandroid.ui
import android.content.Context
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
@ -30,6 +31,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon 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
import androidx.compose.material3.SnackbarDuration.Indefinite import androidx.compose.material3.SnackbarDuration.Indefinite
import androidx.compose.material3.SnackbarDuration.Short import androidx.compose.material3.SnackbarDuration.Short
import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHost
@ -52,6 +54,7 @@ import androidx.compose.ui.composed
import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
@ -69,6 +72,10 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopAp
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.designsystem.theme.GradientColors import com.google.samples.apps.nowinandroid.core.designsystem.theme.GradientColors
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalGradientColors import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalGradientColors
import com.google.samples.apps.nowinandroid.core.model.data.MessageData
import com.google.samples.apps.nowinandroid.core.model.data.MessageType.MESSAGE
import com.google.samples.apps.nowinandroid.core.model.data.MessageType.OFFLINE
import com.google.samples.apps.nowinandroid.core.model.data.MessageType.UNKNOWN
import com.google.samples.apps.nowinandroid.feature.settings.SettingsDialog import com.google.samples.apps.nowinandroid.feature.settings.SettingsDialog
import com.google.samples.apps.nowinandroid.navigation.NiaNavHost import com.google.samples.apps.nowinandroid.navigation.NiaNavHost
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
@ -81,6 +88,8 @@ fun NiaApp(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(), windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
) { ) {
val context = LocalContext.current
val shouldShowGradientBackground = val shouldShowGradientBackground =
appState.currentTopLevelDestination == TopLevelDestination.FOR_YOU appState.currentTopLevelDestination == TopLevelDestination.FOR_YOU
var showSettingsDialog by rememberSaveable { mutableStateOf(false) } var showSettingsDialog by rememberSaveable { mutableStateOf(false) }
@ -95,16 +104,30 @@ fun NiaApp(
) { ) {
val snackbarHostState = remember { SnackbarHostState() } val snackbarHostState = remember { SnackbarHostState() }
val isOffline by appState.isOffline.collectAsStateWithLifecycle() val stateMessage by appState.stateMessage.collectAsStateWithLifecycle()
// If user is not connected to the internet show a snack bar to inform them. LaunchedEffect(stateMessage) {
val notConnectedMessage = stringResource(R.string.not_connected) stateMessage?.let { message ->
LaunchedEffect(isOffline) {
if (isOffline) { //Text and Duration values dictated by the UI
snackbarHostState.showSnackbar( val (text, duration) = getSnackbarValues(context, message)
message = notConnectedMessage,
duration = Indefinite, // Determine whether user clicked action button
) val snackBarResult = snackbarHostState.showSnackbar(
message = text,
actionLabel = message.label,
duration = duration,
) == ActionPerformed
// Handle result action
if (snackBarResult) {
message.onConfirm?.invoke()
} else {
message.onDelay?.invoke()
}
// Remove Message from List
appState.errorMonitor.clearMessage(message)
} }
} }
@ -271,3 +294,11 @@ private fun NavDestination?.isRouteInHierarchy(route: KClass<*>) =
this?.hierarchy?.any { this?.hierarchy?.any {
it.hasRoute(route) it.hasRoute(route)
} ?: false } ?: false
private fun getSnackbarValues(context: Context, message: MessageData): Pair<String, SnackbarDuration> {
return when (message.type) {
OFFLINE -> context.getString(R.string.not_connected) to SnackbarDuration.Indefinite
is MESSAGE -> (message.type as MESSAGE).value to SnackbarDuration.Long
UNKNOWN -> context.getString(R.string.unknown_error) to SnackbarDuration.Short
}
}

@ -17,4 +17,5 @@
<resources> <resources>
<string name="app_name">Now in Android</string> <string name="app_name">Now in Android</string>
<string name="not_connected">⚠️ You arent connected to the internet</string> <string name="not_connected">⚠️ You arent connected to the internet</string>
<string name="unknown_error">Unknown Error</string>
</resources> </resources>

Loading…
Cancel
Save