Skip to content

Commit

Permalink
nom nom snackbars
Browse files Browse the repository at this point in the history
  • Loading branch information
evan10s committed Aug 12, 2024
1 parent 368cd01 commit 5bb4cf7
Show file tree
Hide file tree
Showing 12 changed files with 333 additions and 139 deletions.
113 changes: 59 additions & 54 deletions app/src/main/java/org/robojackets/apiary/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
Expand Down Expand Up @@ -59,6 +60,7 @@ import org.robojackets.apiary.auth.ui.AuthenticationScreen
import org.robojackets.apiary.base.GlobalSettings
import org.robojackets.apiary.base.model.AttendableType
import org.robojackets.apiary.base.ui.nfc.NfcRequired
import org.robojackets.apiary.base.ui.snackbar.SnackbarControllerProvider
import org.robojackets.apiary.base.ui.theme.Apiary_MobileTheme
import org.robojackets.apiary.merchandise.ui.MerchandiseDistributionScreen
import org.robojackets.apiary.merchandise.ui.MerchandiseIndexScreen
Expand Down Expand Up @@ -182,64 +184,67 @@ class MainActivity : ComponentActivity() {
navReady = true
}

// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colorScheme.background) {
ModalBottomSheetLayout(bottomSheetNavigator) {
UpdateGate(
navReady = navReady,
onShowRequiredUpdatePrompt = {
navigationManager.navigate(
NavigationActions.UpdatePrompts.anyScreenToRequiredUpdatePrompt()
)
},
onShowOptionalUpdatePrompt = {
navigationManager.navigate(
NavigationActions.UpdatePrompts.anyScreenToOptionalUpdatePrompt()
)
},
onShowUpdateInProgressScreen = {
navigationManager.navigate(
NavigationActions.UpdatePrompts.anyScreenToUpdateInProgress()
)
}
) {
Scaffold(
topBar = { AppTopBar(settings.appEnv.production) },
bottomBar = {
val current = currentRoute(navController)
if (shouldShowBottomNav(nfcEnabled, current)) {
NavigationBar {
navItems.forEach { screen ->
NavigationBarItem(
icon = {
Icon(
screen.icon,
contentDescription = screen.imgContentDescriptor
)
},
label = { Text(stringResource(screen.resourceId)) },
selected = currentDestination
?.hierarchy
?.any {
it.route == screen.navigationDestination
} == true,
onClick = {
navigationManager.navigate(
NavigationActions.BottomNavTabs.withinBottomNavTabs(
screen.navigationDestination,
navController.graph.findStartDestination().id
SnackbarControllerProvider { snackbarHost ->
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colorScheme.background) {
ModalBottomSheetLayout(bottomSheetNavigator) {
UpdateGate(
navReady = navReady,
onShowRequiredUpdatePrompt = {
navigationManager.navigate(
NavigationActions.UpdatePrompts.anyScreenToRequiredUpdatePrompt()
)
},
onShowOptionalUpdatePrompt = {
navigationManager.navigate(
NavigationActions.UpdatePrompts.anyScreenToOptionalUpdatePrompt()
)
},
onShowUpdateInProgressScreen = {
navigationManager.navigate(
NavigationActions.UpdatePrompts.anyScreenToUpdateInProgress()
)
}
) {
Scaffold(
snackbarHost = { SnackbarHost(hostState = snackbarHost) },
topBar = { AppTopBar(settings.appEnv.production) },
bottomBar = {
val current = currentRoute(navController)
if (shouldShowBottomNav(nfcEnabled, current)) {
NavigationBar {
navItems.forEach { screen ->
NavigationBarItem(
icon = {
Icon(
screen.icon,
contentDescription = screen.imgContentDescriptor
)
},
label = { Text(stringResource(screen.resourceId)) },
selected = currentDestination
?.hierarchy
?.any {
it.route == screen.navigationDestination
} == true,
onClick = {
navigationManager.navigate(
NavigationActions.BottomNavTabs.withinBottomNavTabs(
screen.navigationDestination,
navController.graph.findStartDestination().id
)
)
)
}
)
}
)
}
}
}
}
}
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
NfcRequired(nfcEnabled = nfcEnabled) {
AppNavigation(navController)
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
NfcRequired(nfcEnabled = nfcEnabled) {
AppNavigation(navController)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ package org.robojackets.apiary.attendance.model
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.skydoves.sandwich.StatusCode
import com.skydoves.sandwich.message
import com.skydoves.sandwich.onError
import com.skydoves.sandwich.onException
import com.skydoves.sandwich.onFailure
import com.skydoves.sandwich.onSuccess
import com.skydoves.sandwich.retrofit.statusCode
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
Expand Down Expand Up @@ -77,34 +74,16 @@ class AttendableTypeSelectionViewModel @Inject constructor(

viewModelScope.launch {
loadingUserPermissions.value = true
userRepository.getLoggedInUserInfo().onSuccess {
val missingPermissions = getMissingPermissions(this.data.user.allPermissions, requiredPermissions)
userMissingPermissions.value = missingPermissions
user.value = this.data.user
}
.onError {
when {
statusCode.code >= StatusCode.InternalServerError.code ->
Timber.e(this.message())
else -> Timber.w(this.message())
}

permissionsCheckError.value = when {
this.statusCode.code >= StatusCode.InternalServerError.code ->
"A server error occurred while checking if you have permission to " +
"use this feature. Check your internet connection and try " +
"again, or ask in #it-helpdesk for assistance."
else ->
"An error occurred while checking if you have permission to use " +
"this feature. Check your internet connection and try again, or " +
"ask in #it-helpdesk for assistance."
}
userRepository.getLoggedInUserInfo()
.onSuccess {
val missingPermissions =
getMissingPermissions(this.data.user.allPermissions, requiredPermissions)
userMissingPermissions.value = missingPermissions
user.value = this.data.user
}
.onException {
Timber.e(this.throwable)
permissionsCheckError.value = "An error occurred while checking if you have " +
"permission to use this feature. Check your internet connection and " +
"try again, or ask in #it-helpdesk for assistance."
.onFailure {
Timber.e(this.message())
permissionsCheckError.value = "Error while checking permissions"
}
.also {
loadingUserPermissions.value = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ fun AttendableTypeSelectionScreen(
if (state.permissionsCheckError?.isNotEmpty() == true) {
ErrorMessageWithRetry(
message = state.permissionsCheckError ?: "An unknown error occurred",
onRetry = { viewModel.checkUserAttendanceAccess(forceRefresh = true) }
onRetry = { viewModel.checkUserAttendanceAccess(forceRefresh = true) },
prioritizeRetryButton = true,
)
return@ContentPadding
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import org.robojackets.apiary.auth.model.Permission
import org.robojackets.apiary.auth.model.Permission.*
import org.robojackets.apiary.auth.model.Permission.CREATE_ATTENDANCE
import org.robojackets.apiary.auth.model.Permission.READ_TEAMS_HIDDEN
import org.robojackets.apiary.auth.model.Permission.READ_USERS
import org.robojackets.apiary.base.ui.error.GoToItHelpdesk
import org.robojackets.apiary.base.ui.icons.ErrorIcon
import org.robojackets.apiary.base.ui.theme.Apiary_MobileTheme
import org.robojackets.apiary.base.ui.theme.danger
import org.robojackets.apiary.base.ui.theme.success
import org.robojackets.apiary.base.ui.util.ContentPadding
Expand All @@ -55,26 +58,28 @@ fun InsufficientPermissions(
) {
ErrorIcon(Modifier.size(90.dp), tint = danger)
Text(
text = "$featureName unavailable",
text = "$featureName permissions required",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.padding(top = 12.dp),
)
Text(
text = "You don't have permission to use this feature. Please ask in #it-helpdesk for assistance.",
text = "You don't have permission to use this feature",
modifier = Modifier.padding(top = 12.dp),
textAlign = TextAlign.Center,
)

Row(Modifier.padding(top = 18.dp)) {
OutlinedButton(onClick = { onRefreshRequest() }) {
Text("Try again")
Text("Retry")
}
GoToItHelpdesk(modifier = Modifier.padding(start = 8.dp))
}

TextButton(onClick = {
showPermissionDetailsDialog = true
}, Modifier.padding(top = 0.dp)) {
Text("More info")
Text("View details")
}

if (showPermissionDetailsDialog) {
Expand Down Expand Up @@ -157,12 +162,14 @@ fun PermissionsListItem(hasPermission: Boolean, permissionName: String) {
@Composable
@Preview
fun InsufficientPermissionsPreview() {
ContentPadding {
InsufficientPermissions(
featureName = "Attendance",
onRefreshRequest = {},
missingPermissions = listOf(READ_TEAMS_HIDDEN),
requiredPermissions = listOf(CREATE_ATTENDANCE, READ_USERS, READ_TEAMS_HIDDEN),
)
Apiary_MobileTheme {
ContentPadding {
InsufficientPermissions(
featureName = "Attendance",
onRefreshRequest = {},
missingPermissions = listOf(READ_TEAMS_HIDDEN),
requiredPermissions = listOf(CREATE_ATTENDANCE, READ_USERS, READ_TEAMS_HIDDEN),
)
}
}
}
Loading

0 comments on commit 5bb4cf7

Please sign in to comment.