Skip to content

Commit 6535c65

Browse files
committed
Add offline snackbar notification
1 parent 64fd903 commit 6535c65

File tree

4 files changed

+48
-14
lines changed

4 files changed

+48
-14
lines changed

app/src/main/kotlin/com/espressodev/gptmap/GmApp.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.espressodev.gptmap
22

33
import android.content.res.Resources
4+
import android.util.Log
45
import androidx.compose.foundation.layout.RowScope
56
import androidx.compose.foundation.layout.WindowInsets
67
import androidx.compose.foundation.layout.fillMaxSize
@@ -11,19 +12,23 @@ import androidx.compose.material3.MaterialTheme
1112
import androidx.compose.material3.NavigationBarItem
1213
import androidx.compose.material3.Scaffold
1314
import androidx.compose.material3.Snackbar
15+
import androidx.compose.material3.SnackbarDuration
1416
import androidx.compose.material3.SnackbarHost
1517
import androidx.compose.material3.SnackbarHostState
1618
import androidx.compose.material3.Surface
1719
import androidx.compose.material3.Text
1820
import androidx.compose.runtime.Composable
21+
import androidx.compose.runtime.LaunchedEffect
1922
import androidx.compose.runtime.ReadOnlyComposable
23+
import androidx.compose.runtime.getValue
2024
import androidx.compose.runtime.remember
2125
import androidx.compose.runtime.rememberCoroutineScope
2226
import androidx.compose.ui.Modifier
2327
import androidx.compose.ui.platform.LocalConfiguration
2428
import androidx.compose.ui.platform.LocalContext
2529
import androidx.compose.ui.res.stringResource
2630
import androidx.compose.ui.unit.dp
31+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
2732
import androidx.navigation.NavDestination
2833
import androidx.navigation.NavDestination.Companion.hierarchy
2934
import androidx.navigation.NavHostController
@@ -35,7 +40,7 @@ import com.espressodev.gptmap.feature.map.MapRouteWithArg
3540
import com.espressodev.gptmap.navigation.GmNavHost
3641
import com.espressodev.gptmap.navigation.TopLevelDestination
3742
import kotlinx.coroutines.CoroutineScope
38-
43+
import com.espressodev.gptmap.core.designsystem.R.string as AppText
3944
@Composable
4045
fun GmApp(
4146
networkMonitor: NetworkMonitor,
@@ -47,6 +52,17 @@ fun GmApp(
4752
else -> LoginRoute
4853
}
4954

55+
val isOffline by appState.isOffline.collectAsStateWithLifecycle()
56+
val message = stringResource(id = AppText.not_connected)
57+
LaunchedEffect(isOffline) {
58+
if (isOffline) {
59+
appState.snackbarHostState.showSnackbar(
60+
message = message,
61+
duration = SnackbarDuration.Indefinite
62+
)
63+
}
64+
}
65+
5066
Surface(color = MaterialTheme.colorScheme.background, modifier = Modifier.fillMaxSize()) {
5167
Scaffold(
5268
snackbarHost = {

app/src/main/kotlin/com/espressodev/gptmap/GmAppState.kt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.espressodev.gptmap
22

33
import android.content.res.Resources
4+
import androidx.compose.material3.SnackbarDuration
45
import androidx.compose.material3.SnackbarHostState
56
import androidx.compose.runtime.Composable
67
import androidx.compose.runtime.Stable
@@ -22,7 +23,10 @@ import com.espressodev.gptmap.navigation.TopLevelDestination.FAVOURITE
2223
import com.espressodev.gptmap.navigation.TopLevelDestination.MAP
2324
import com.espressodev.gptmap.navigation.TopLevelDestination.SCREENSHOT_GALLERY
2425
import kotlinx.coroutines.CoroutineScope
26+
import kotlinx.coroutines.flow.SharingStarted
2527
import kotlinx.coroutines.flow.filterNotNull
28+
import kotlinx.coroutines.flow.map
29+
import kotlinx.coroutines.flow.stateIn
2630
import kotlinx.coroutines.launch
2731

2832
@Stable
@@ -37,13 +41,25 @@ class GmAppState(
3741
init {
3842
coroutineScope.launch {
3943
snackbarManager.snackbarMessages.filterNotNull().collect { snackbarMessage ->
40-
val text = snackbarMessage.toMessage(resources)
41-
snackbarHostState.showSnackbar(text, withDismissAction = true)
44+
val text = snackbarMessage.first.toMessage(resources)
45+
snackbarHostState.showSnackbar(
46+
text,
47+
withDismissAction = true,
48+
duration = snackbarMessage.second ?: SnackbarDuration.Short
49+
)
4250
snackbarManager.clean()
4351
}
4452
}
4553
}
4654

55+
val isOffline = networkMonitor.isOnline
56+
.map(Boolean::not)
57+
.stateIn(
58+
scope = coroutineScope,
59+
started = SharingStarted.WhileSubscribed(5_000),
60+
initialValue = false,
61+
)
62+
4763
val topLevelDestination: List<TopLevelDestination> = TopLevelDestination.entries
4864

4965
val currentDestination: NavDestination?

app/src/main/kotlin/com/espressodev/gptmap/MainActivityViewModel.kt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,22 @@ class MainActivityViewModel @Inject constructor(
2525
) : ViewModel() {
2626
private val _accountState = MutableStateFlow(AccountState.Loading)
2727
val accountService = _accountState.asStateFlow()
28+
2829
init {
2930
viewModelScope.launch {
30-
if (accountService.isEmailVerified) {
31-
accountService.firebaseUser?.getIdToken(true)?.await()?.token?.let {
32-
realmAccountService.loginWithEmail(it).getOrElse {
33-
_accountState.update { AccountState.UserNotSignIn }
34-
}.run {
35-
_accountState.update { AccountState.UserAlreadySignIn }
31+
runCatching {
32+
if (accountService.isEmailVerified) {
33+
accountService.firebaseUser?.getIdToken(true)?.await()?.token?.let {
34+
realmAccountService.loginWithEmail(it).getOrElse {
35+
_accountState.update { AccountState.UserNotSignIn }
36+
}.run {
37+
_accountState.update { AccountState.UserAlreadySignIn }
38+
}
3639
}
40+
} else {
41+
_accountState.update { AccountState.UserNotSignIn }
3742
}
38-
} else {
43+
}.onFailure {
3944
_accountState.update { AccountState.UserNotSignIn }
4045
}
4146
}

app/src/main/kotlin/com/espressodev/gptmap/navigation/GmNavHost.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,7 @@ fun GmNavHost(
6363
popUp = navController::popBackStack,
6464
navigateToMap = navController::navigateToMap
6565
)
66-
screenshotScreen(
67-
popUp = navController::popBackStack,
68-
navigateToMap = navController::navigateToMap
69-
)
66+
screenshotScreen(popUp = navController::popBackStack)
7067
screenshotGalleryScreen(popUp = navController::popBackStack)
7168
profileScreen(
7269
popUp = navController::popBackStack,

0 commit comments

Comments
 (0)