Loading cardinal-android/app/src/main/java/earth/maps/cardinal/ui/core/AppContent.kt +598 −468 Original line number Diff line number Diff line Loading @@ -243,6 +243,153 @@ fun AppContent( Screen.HOME_SEARCH, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> HomeRoute(state, homeViewModel, navController, topOfBackStack, appPreferenceRepository, backStackEntry) } composable( Screen.NEARBY_POI, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> NearbyPoiRoute(state, nearbyViewModel, navController, topOfBackStack, backStackEntry) } composable( Screen.NEARBY_TRANSIT, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> NearbyTransitRoute(state, transitViewModel, navController, topOfBackStack, backStackEntry) } composable( Screen.PLACE_CARD, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> PlaceCardRoute(state, navController, topOfBackStack, appPreferenceRepository, backStackEntry) } composable( Screen.OFFLINE_AREAS, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> OfflineAreasRoute(state, navController, topOfBackStack, appPreferenceRepository, backStackEntry) } composable( Screen.SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { SettingsRoute(state, navController) } composable( Screen.OFFLINE_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { PrivacySettingsRoute(state, navController) } composable( Screen.ACCESSIBILITY_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { AccessibilitySettingsRoute(state, navController) } composable( Screen.ADVANCED_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { AdvancedSettingsRoute(state, navController) } composable( Screen.ROUTING_PROFILES, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { RoutingProfilesRoute(state, navController) } composable( Screen.PROFILE_EDITOR, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { backStackEntry -> ProfileEditorRoute(state, navController, backStackEntry) } composable( Screen.MANAGE_PLACES, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { backStackEntry -> ManagePlacesRoute(state, navController, backStackEntry) } composable( Screen.DIRECTIONS, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> DirectionsRoute(state, mapViewModel, navController, topOfBackStack, appPreferenceRepository, hasLocationPermission, onRequestLocationPermission, hasNotificationPermission, onRequestNotificationPermission, backStackEntry) } composable( Screen.TRANSIT_ITINERARY_DETAIL, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> TransitItineraryDetailRoute(state, navController, topOfBackStack, appPreferenceRepository, backStackEntry) } composable(Screen.TURN_BY_TURN) { backStackEntry -> TurnByTurnRoute(state, routeRepository, port, backStackEntry) } } Box(modifier = Modifier.fillMaxSize()) { // Animated toolbar positioned below the scaffold AnimatedVisibility( modifier = Modifier.align(Alignment.BottomCenter), visible = state.showToolbar, enter = slideInVertically( initialOffsetY = { it }, animationSpec = tween(300) ), exit = slideOutVertically( targetOffsetY = { it }, animationSpec = tween(300) ), ) { CardinalToolbar(navController, onSearchDoublePress = { homeViewModel.expandSearch() }) } } } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun HomeRoute( state: AppContentState, homeViewModel: HomeViewModel, navController: NavHostController, topOfBackStack: NavBackStackEntry?, appPreferenceRepository: AppPreferenceRepository, backStackEntry: NavBackStackEntry ) { state.showToolbar = true HomeScreenComposable( viewModel = homeViewModel, Loading @@ -264,12 +411,16 @@ fun AppContent( ) } composable( Screen.NEARBY_POI, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun NearbyPoiRoute( state: AppContentState, nearbyViewModel: NearbyViewModel, navController: NavHostController, topOfBackStack: NavBackStackEntry?, backStackEntry: NavBackStackEntry ) { state.showToolbar = true val bottomSheetState = rememberBottomSheetState( initialValue = BottomSheetValue.Collapsed ) Loading @@ -289,13 +440,17 @@ fun AppContent( } }, ) } composable( Screen.NEARBY_TRANSIT, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun NearbyTransitRoute( state: AppContentState, transitViewModel: TransitScreenViewModel, navController: NavHostController, topOfBackStack: NavBackStackEntry?, backStackEntry: NavBackStackEntry ) { state.showToolbar = true val bottomSheetState = rememberBottomSheetState( Loading @@ -319,17 +474,114 @@ fun AppContent( ) } composable( Screen.PLACE_CARD, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun SettingsRoute(state: AppContentState, navController: NavHostController) { state.showToolbar = true val viewModel = hiltViewModel<SettingsViewModel>() SettingsScreen(navController = navController, viewModel = viewModel) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun PrivacySettingsRoute(state: AppContentState, navController: NavHostController) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() PrivacySettingsScreen( viewModel = viewModel, onDismiss = { navController.popBackStack() }, onNavigateToOfflineAreas = { NavigationUtils.navigate( navController, Screen.OfflineAreas ) }, ) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun AccessibilitySettingsRoute(state: AppContentState, navController: NavHostController) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() AccessibilitySettingsScreen(viewModel = viewModel, onDismiss = { navController.popBackStack() }) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun AdvancedSettingsRoute(state: AppContentState, navController: NavHostController) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() AdvancedSettingsScreen(viewModel = viewModel) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun RoutingProfilesRoute(state: AppContentState, navController: NavHostController) { state.showToolbar = true RoutingProfilesScreen(navController = navController) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun ProfileEditorRoute(state: AppContentState, navController: NavHostController, backStackEntry: NavBackStackEntry) { LaunchedEffect(key1 = Unit) { state.mapPins.clear() } val snackBarHostState = remember { SnackbarHostState() } val profileId = backStackEntry.arguments?.getString("profileId") Scaffold( snackbarHost = { SnackbarHost(snackBarHostState) }, contentWindowInsets = WindowInsets.safeDrawing, content = { padding -> Box(modifier = Modifier.padding(padding)) { ProfileEditorScreen( navController = navController, profileId = profileId, snackBarHostState = snackBarHostState ) } }) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun ManagePlacesRoute(state: AppContentState, navController: NavHostController, backStackEntry: NavBackStackEntry) { state.showToolbar = true val listIdRaw = backStackEntry.arguments?.getString("listId") val listId = if (listIdRaw.isNullOrBlank()) { null } else { listIdRaw } val parentsGson = backStackEntry.arguments?.getString("parents")?.let { Uri.decode(it) } val parents: List<String> = parentsGson?.let { Gson().fromJson(it, object : TypeToken<List<String>>() {}.type) } ?: emptyList() ManagePlacesScreen( navController = navController, listId = listId, parents = parents, ) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun PlaceCardRoute( state: AppContentState, navController: NavHostController, topOfBackStack: NavBackStackEntry?, appPreferenceRepository: AppPreferenceRepository, backStackEntry: NavBackStackEntry ) { state.showToolbar = false val bottomSheetState = rememberBottomSheetState( initialValue = BottomSheetValue.Collapsed ) val scaffoldState = rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState) val scaffoldState = rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState) LaunchedEffect(key1 = Unit) { // The place card starts partially expanded. Loading Loading @@ -402,10 +654,15 @@ fun AppContent( } } composable( Screen.OFFLINE_AREAS, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun OfflineAreasRoute( state: AppContentState, navController: NavHostController, topOfBackStack: NavBackStackEntry?, appPreferenceRepository: AppPreferenceRepository, backStackEntry: NavBackStackEntry ) { state.showToolbar = true val bottomSheetState = rememberBottomSheetState( initialValue = BottomSheetValue.Collapsed Loading Loading @@ -480,141 +737,20 @@ fun AppContent( } } composable( Screen.SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { state.showToolbar = true SettingsScreen( navController = navController, viewModel = hiltViewModel(), ) } composable( Screen.OFFLINE_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() PrivacySettingsScreen( viewModel = viewModel, onDismiss = { navController.popBackStack() }, onNavigateToOfflineAreas = { NavigationUtils.navigate( navController, Screen.OfflineAreas ) }, ) } composable( Screen.ACCESSIBILITY_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() AccessibilitySettingsScreen( viewModel = viewModel, onDismiss = { navController.popBackStack() }) } composable( Screen.ADVANCED_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() AdvancedSettingsScreen( viewModel = viewModel ) } composable( Screen.ROUTING_PROFILES, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, @OptIn(ExperimentalMaterial3Api::class) @Composable private fun DirectionsRoute( state: AppContentState, mapViewModel: MapViewModel, navController: NavHostController, topOfBackStack: NavBackStackEntry?, appPreferenceRepository: AppPreferenceRepository, hasLocationPermission: Boolean, onRequestLocationPermission: () -> Unit, hasNotificationPermission: Boolean, onRequestNotificationPermission: () -> Unit, backStackEntry: NavBackStackEntry ) { state.showToolbar = true RoutingProfilesScreen( navController = navController ) } composable( Screen.PROFILE_EDITOR, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { backStackEntry -> LaunchedEffect(key1 = Unit) { state.mapPins.clear() } val snackBarHostState = remember { SnackbarHostState() } val profileId = backStackEntry.arguments?.getString("profileId") Scaffold( snackbarHost = { SnackbarHost(snackBarHostState) }, contentWindowInsets = WindowInsets.safeDrawing, content = { padding -> Box(modifier = Modifier.padding(padding)) { ProfileEditorScreen( navController = navController, profileId = profileId, snackBarHostState = snackBarHostState ) } }) } composable( Screen.MANAGE_PLACES, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { backStackEntry -> state.showToolbar = true val listIdRaw = backStackEntry.arguments?.getString("listId") // The screen is set up to take a real value, or null. What we end up with at this point (sometimes?) // is an empty string instead of null. val listId = if (listIdRaw.isNullOrBlank()) { null } else { listIdRaw } val parentsGson = backStackEntry.arguments?.getString("parents")?.let { Uri.decode(it) } val parents: List<String> = parentsGson?.let { Gson().fromJson(it, object : TypeToken<List<String>>() {}.type) } ?: emptyList() ManagePlacesScreen( navController = navController, listId = listId, parents = parents, ) } composable( Screen.DIRECTIONS, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> state.showToolbar = false val bottomSheetState = rememberBottomSheetState(initialValue = BottomSheetValue.Collapsed) Loading Loading @@ -695,10 +831,15 @@ fun AppContent( ) } composable( Screen.TRANSIT_ITINERARY_DETAIL, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun TransitItineraryDetailRoute( state: AppContentState, navController: NavHostController, topOfBackStack: NavBackStackEntry?, appPreferenceRepository: AppPreferenceRepository, backStackEntry: NavBackStackEntry ) { state.showToolbar = false val bottomSheetState = rememberBottomSheetState( Loading Loading @@ -797,7 +938,14 @@ fun AppContent( } } composable(Screen.TURN_BY_TURN) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun TurnByTurnRoute( state: AppContentState, routeRepository: RouteRepository, port: Int?, backStackEntry: NavBackStackEntry ) { state.showToolbar = false val routeId = backStackEntry.arguments?.getString("routeId") val routingModeJson = backStackEntry.arguments?.getString("routingMode") Loading Loading @@ -826,24 +974,6 @@ fun AppContent( ) } } } Box(modifier = Modifier.fillMaxSize()) { // Animated toolbar positioned below the scaffold AnimatedVisibility( modifier = Modifier.align(Alignment.BottomCenter), visible = state.showToolbar, enter = slideInVertically( initialOffsetY = { it }, animationSpec = tween(300) ), exit = slideOutVertically( targetOffsetY = { it }, animationSpec = tween(300) ), ) { CardinalToolbar(navController, onSearchDoublePress = { homeViewModel.expandSearch() }) } } } @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable Loading Loading
cardinal-android/app/src/main/java/earth/maps/cardinal/ui/core/AppContent.kt +598 −468 Original line number Diff line number Diff line Loading @@ -243,6 +243,153 @@ fun AppContent( Screen.HOME_SEARCH, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> HomeRoute(state, homeViewModel, navController, topOfBackStack, appPreferenceRepository, backStackEntry) } composable( Screen.NEARBY_POI, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> NearbyPoiRoute(state, nearbyViewModel, navController, topOfBackStack, backStackEntry) } composable( Screen.NEARBY_TRANSIT, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> NearbyTransitRoute(state, transitViewModel, navController, topOfBackStack, backStackEntry) } composable( Screen.PLACE_CARD, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> PlaceCardRoute(state, navController, topOfBackStack, appPreferenceRepository, backStackEntry) } composable( Screen.OFFLINE_AREAS, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> OfflineAreasRoute(state, navController, topOfBackStack, appPreferenceRepository, backStackEntry) } composable( Screen.SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { SettingsRoute(state, navController) } composable( Screen.OFFLINE_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { PrivacySettingsRoute(state, navController) } composable( Screen.ACCESSIBILITY_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { AccessibilitySettingsRoute(state, navController) } composable( Screen.ADVANCED_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { AdvancedSettingsRoute(state, navController) } composable( Screen.ROUTING_PROFILES, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { RoutingProfilesRoute(state, navController) } composable( Screen.PROFILE_EDITOR, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { backStackEntry -> ProfileEditorRoute(state, navController, backStackEntry) } composable( Screen.MANAGE_PLACES, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { backStackEntry -> ManagePlacesRoute(state, navController, backStackEntry) } composable( Screen.DIRECTIONS, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> DirectionsRoute(state, mapViewModel, navController, topOfBackStack, appPreferenceRepository, hasLocationPermission, onRequestLocationPermission, hasNotificationPermission, onRequestNotificationPermission, backStackEntry) } composable( Screen.TRANSIT_ITINERARY_DETAIL, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> TransitItineraryDetailRoute(state, navController, topOfBackStack, appPreferenceRepository, backStackEntry) } composable(Screen.TURN_BY_TURN) { backStackEntry -> TurnByTurnRoute(state, routeRepository, port, backStackEntry) } } Box(modifier = Modifier.fillMaxSize()) { // Animated toolbar positioned below the scaffold AnimatedVisibility( modifier = Modifier.align(Alignment.BottomCenter), visible = state.showToolbar, enter = slideInVertically( initialOffsetY = { it }, animationSpec = tween(300) ), exit = slideOutVertically( targetOffsetY = { it }, animationSpec = tween(300) ), ) { CardinalToolbar(navController, onSearchDoublePress = { homeViewModel.expandSearch() }) } } } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun HomeRoute( state: AppContentState, homeViewModel: HomeViewModel, navController: NavHostController, topOfBackStack: NavBackStackEntry?, appPreferenceRepository: AppPreferenceRepository, backStackEntry: NavBackStackEntry ) { state.showToolbar = true HomeScreenComposable( viewModel = homeViewModel, Loading @@ -264,12 +411,16 @@ fun AppContent( ) } composable( Screen.NEARBY_POI, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun NearbyPoiRoute( state: AppContentState, nearbyViewModel: NearbyViewModel, navController: NavHostController, topOfBackStack: NavBackStackEntry?, backStackEntry: NavBackStackEntry ) { state.showToolbar = true val bottomSheetState = rememberBottomSheetState( initialValue = BottomSheetValue.Collapsed ) Loading @@ -289,13 +440,17 @@ fun AppContent( } }, ) } composable( Screen.NEARBY_TRANSIT, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun NearbyTransitRoute( state: AppContentState, transitViewModel: TransitScreenViewModel, navController: NavHostController, topOfBackStack: NavBackStackEntry?, backStackEntry: NavBackStackEntry ) { state.showToolbar = true val bottomSheetState = rememberBottomSheetState( Loading @@ -319,17 +474,114 @@ fun AppContent( ) } composable( Screen.PLACE_CARD, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun SettingsRoute(state: AppContentState, navController: NavHostController) { state.showToolbar = true val viewModel = hiltViewModel<SettingsViewModel>() SettingsScreen(navController = navController, viewModel = viewModel) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun PrivacySettingsRoute(state: AppContentState, navController: NavHostController) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() PrivacySettingsScreen( viewModel = viewModel, onDismiss = { navController.popBackStack() }, onNavigateToOfflineAreas = { NavigationUtils.navigate( navController, Screen.OfflineAreas ) }, ) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun AccessibilitySettingsRoute(state: AppContentState, navController: NavHostController) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() AccessibilitySettingsScreen(viewModel = viewModel, onDismiss = { navController.popBackStack() }) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun AdvancedSettingsRoute(state: AppContentState, navController: NavHostController) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() AdvancedSettingsScreen(viewModel = viewModel) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun RoutingProfilesRoute(state: AppContentState, navController: NavHostController) { state.showToolbar = true RoutingProfilesScreen(navController = navController) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun ProfileEditorRoute(state: AppContentState, navController: NavHostController, backStackEntry: NavBackStackEntry) { LaunchedEffect(key1 = Unit) { state.mapPins.clear() } val snackBarHostState = remember { SnackbarHostState() } val profileId = backStackEntry.arguments?.getString("profileId") Scaffold( snackbarHost = { SnackbarHost(snackBarHostState) }, contentWindowInsets = WindowInsets.safeDrawing, content = { padding -> Box(modifier = Modifier.padding(padding)) { ProfileEditorScreen( navController = navController, profileId = profileId, snackBarHostState = snackBarHostState ) } }) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun ManagePlacesRoute(state: AppContentState, navController: NavHostController, backStackEntry: NavBackStackEntry) { state.showToolbar = true val listIdRaw = backStackEntry.arguments?.getString("listId") val listId = if (listIdRaw.isNullOrBlank()) { null } else { listIdRaw } val parentsGson = backStackEntry.arguments?.getString("parents")?.let { Uri.decode(it) } val parents: List<String> = parentsGson?.let { Gson().fromJson(it, object : TypeToken<List<String>>() {}.type) } ?: emptyList() ManagePlacesScreen( navController = navController, listId = listId, parents = parents, ) } @OptIn(ExperimentalMaterial3Api::class) @Composable private fun PlaceCardRoute( state: AppContentState, navController: NavHostController, topOfBackStack: NavBackStackEntry?, appPreferenceRepository: AppPreferenceRepository, backStackEntry: NavBackStackEntry ) { state.showToolbar = false val bottomSheetState = rememberBottomSheetState( initialValue = BottomSheetValue.Collapsed ) val scaffoldState = rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState) val scaffoldState = rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState) LaunchedEffect(key1 = Unit) { // The place card starts partially expanded. Loading Loading @@ -402,10 +654,15 @@ fun AppContent( } } composable( Screen.OFFLINE_AREAS, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun OfflineAreasRoute( state: AppContentState, navController: NavHostController, topOfBackStack: NavBackStackEntry?, appPreferenceRepository: AppPreferenceRepository, backStackEntry: NavBackStackEntry ) { state.showToolbar = true val bottomSheetState = rememberBottomSheetState( initialValue = BottomSheetValue.Collapsed Loading Loading @@ -480,141 +737,20 @@ fun AppContent( } } composable( Screen.SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { state.showToolbar = true SettingsScreen( navController = navController, viewModel = hiltViewModel(), ) } composable( Screen.OFFLINE_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() PrivacySettingsScreen( viewModel = viewModel, onDismiss = { navController.popBackStack() }, onNavigateToOfflineAreas = { NavigationUtils.navigate( navController, Screen.OfflineAreas ) }, ) } composable( Screen.ACCESSIBILITY_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() AccessibilitySettingsScreen( viewModel = viewModel, onDismiss = { navController.popBackStack() }) } composable( Screen.ADVANCED_SETTINGS, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { state.showToolbar = true val viewModel: SettingsViewModel = hiltViewModel() AdvancedSettingsScreen( viewModel = viewModel ) } composable( Screen.ROUTING_PROFILES, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, @OptIn(ExperimentalMaterial3Api::class) @Composable private fun DirectionsRoute( state: AppContentState, mapViewModel: MapViewModel, navController: NavHostController, topOfBackStack: NavBackStackEntry?, appPreferenceRepository: AppPreferenceRepository, hasLocationPermission: Boolean, onRequestLocationPermission: () -> Unit, hasNotificationPermission: Boolean, onRequestNotificationPermission: () -> Unit, backStackEntry: NavBackStackEntry ) { state.showToolbar = true RoutingProfilesScreen( navController = navController ) } composable( Screen.PROFILE_EDITOR, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { backStackEntry -> LaunchedEffect(key1 = Unit) { state.mapPins.clear() } val snackBarHostState = remember { SnackbarHostState() } val profileId = backStackEntry.arguments?.getString("profileId") Scaffold( snackbarHost = { SnackbarHost(snackBarHostState) }, contentWindowInsets = WindowInsets.safeDrawing, content = { padding -> Box(modifier = Modifier.padding(padding)) { ProfileEditorScreen( navController = navController, profileId = profileId, snackBarHostState = snackBarHostState ) } }) } composable( Screen.MANAGE_PLACES, enterTransition = { slideInHorizontally(initialOffsetX = { it }) }, exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) }, popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) }, popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) }, ) { backStackEntry -> state.showToolbar = true val listIdRaw = backStackEntry.arguments?.getString("listId") // The screen is set up to take a real value, or null. What we end up with at this point (sometimes?) // is an empty string instead of null. val listId = if (listIdRaw.isNullOrBlank()) { null } else { listIdRaw } val parentsGson = backStackEntry.arguments?.getString("parents")?.let { Uri.decode(it) } val parents: List<String> = parentsGson?.let { Gson().fromJson(it, object : TypeToken<List<String>>() {}.type) } ?: emptyList() ManagePlacesScreen( navController = navController, listId = listId, parents = parents, ) } composable( Screen.DIRECTIONS, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> state.showToolbar = false val bottomSheetState = rememberBottomSheetState(initialValue = BottomSheetValue.Collapsed) Loading Loading @@ -695,10 +831,15 @@ fun AppContent( ) } composable( Screen.TRANSIT_ITINERARY_DETAIL, enterTransition = { slideInVertically(initialOffsetY = { it }) }, exitTransition = { fadeOut(animationSpec = tween(600)) }) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun TransitItineraryDetailRoute( state: AppContentState, navController: NavHostController, topOfBackStack: NavBackStackEntry?, appPreferenceRepository: AppPreferenceRepository, backStackEntry: NavBackStackEntry ) { state.showToolbar = false val bottomSheetState = rememberBottomSheetState( Loading Loading @@ -797,7 +938,14 @@ fun AppContent( } } composable(Screen.TURN_BY_TURN) { backStackEntry -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun TurnByTurnRoute( state: AppContentState, routeRepository: RouteRepository, port: Int?, backStackEntry: NavBackStackEntry ) { state.showToolbar = false val routeId = backStackEntry.arguments?.getString("routeId") val routingModeJson = backStackEntry.arguments?.getString("routingMode") Loading Loading @@ -826,24 +974,6 @@ fun AppContent( ) } } } Box(modifier = Modifier.fillMaxSize()) { // Animated toolbar positioned below the scaffold AnimatedVisibility( modifier = Modifier.align(Alignment.BottomCenter), visible = state.showToolbar, enter = slideInVertically( initialOffsetY = { it }, animationSpec = tween(300) ), exit = slideOutVertically( targetOffsetY = { it }, animationSpec = tween(300) ), ) { CardinalToolbar(navController, onSearchDoublePress = { homeViewModel.expandSearch() }) } } } @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable Loading