diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/core/AppContent.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/core/AppContent.kt index b6f893e1c53ee631727d3efeb32d139735f3c133..648024b0afd34decdc9f562980818e9118a7225e 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/core/AppContent.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/core/AppContent.kt @@ -110,7 +110,7 @@ import earth.maps.cardinal.routing.RouteRepository import earth.maps.cardinal.ui.directions.DirectionsScreen import earth.maps.cardinal.ui.directions.DirectionsViewModel import earth.maps.cardinal.ui.directions.RouteDisplayHandler -import earth.maps.cardinal.ui.directions.TurnByTurnNavigationScreen +import earth.maps.cardinal.ui.navigation.TurnByTurnNavigationScreen import earth.maps.cardinal.ui.home.HomeScreen import earth.maps.cardinal.ui.home.HomeViewModel import earth.maps.cardinal.ui.home.NearbyScreenContent diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/navigation/NavigationChrome.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/navigation/NavigationChrome.kt new file mode 100644 index 0000000000000000000000000000000000000000..27b2c8aa01e04e60169cb90b148008c1e9246655 --- /dev/null +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/navigation/NavigationChrome.kt @@ -0,0 +1,150 @@ +package earth.maps.cardinal.ui.navigation + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.DpSize +import androidx.compose.ui.unit.dp +import com.stadiamaps.ferrostar.composeui.config.NavigationViewComponentBuilder +import com.stadiamaps.ferrostar.composeui.models.CameraControlState +import com.stadiamaps.ferrostar.composeui.theme.DefaultInstructionRowTheme +import com.stadiamaps.ferrostar.composeui.theme.DefaultRoadNameViewTheme +import com.stadiamaps.ferrostar.composeui.theme.InstructionRowTheme +import com.stadiamaps.ferrostar.composeui.theme.NavigationUITheme +import com.stadiamaps.ferrostar.composeui.theme.RoadNameViewTheme +import com.stadiamaps.ferrostar.composeui.theme.TripProgressViewStyle +import com.stadiamaps.ferrostar.composeui.theme.TripProgressViewTheme +import com.stadiamaps.ferrostar.composeui.views.components.CurrentRoadNameView +import com.stadiamaps.ferrostar.composeui.views.components.InstructionsView +import com.stadiamaps.ferrostar.composeui.views.components.TripProgressView +import com.stadiamaps.ferrostar.core.NavigationUiState +import kotlin.time.ExperimentalTime + +object CardinalNavigationUITheme : NavigationUITheme { + override val instructionRowTheme: InstructionRowTheme + @Composable get() = DefaultInstructionRowTheme + + override val roadNameViewTheme: RoadNameViewTheme + @Composable get() = DefaultRoadNameViewTheme + + override val tripProgressViewTheme: TripProgressViewTheme + @Composable get() = CardinalTripProgressViewTheme + + override val buttonSize: DpSize + @Composable get() = DpSize(56.dp, 56.dp) +} + +object CardinalTripProgressViewTheme : TripProgressViewTheme { + override val style: TripProgressViewStyle + @Composable get() = TripProgressViewStyle.SIMPLIFIED + + override val measurementTextStyle: TextStyle + @Composable + get() = + MaterialTheme.typography.titleLarge.copy( + color = MaterialTheme.colorScheme.onSurface, fontWeight = FontWeight.Normal) + + override val secondaryTextStyle: TextStyle + @Composable + get() = + MaterialTheme.typography.labelSmall.copy(color = MaterialTheme.colorScheme.onSurfaceVariant) + + override val exitIconColor: Color + @Composable get() = MaterialTheme.colorScheme.onSecondary + + override val exitButtonBackgroundColor: Color + @Composable get() = MaterialTheme.colorScheme.secondary + + override val backgroundColor: Color + @Composable get() = MaterialTheme.colorScheme.surface +} + + +@Composable +fun CardinalInstructionsView(modifier: Modifier, uiState: NavigationUiState) { + uiState.visualInstruction?.let { instructions -> + InstructionsView( + modifier = modifier, + instructions = instructions, + theme = CardinalNavigationUITheme.instructionRowTheme, + remainingSteps = uiState.remainingSteps, + distanceToNextManeuver = uiState.progress?.distanceToNextManeuver + ) + } +} + +@OptIn(ExperimentalTime::class) +@Composable +fun CardinalProgressView( + modifier: Modifier, + uiState: NavigationUiState, + onTapExit: (() -> Unit)? +) { + uiState.progress?.let { progress -> + TripProgressView( + modifier = modifier, + theme = CardinalNavigationUITheme.tripProgressViewTheme, + progress = progress, + onTapExit = onTapExit + ) + } +} + +@Composable +fun CardinalRoadNameView( + modifier: Modifier, + roadName: String?, + cameraControlState: CameraControlState +) { + if (cameraControlState is CameraControlState.ShowRouteOverview) { + roadName?.let { roadName -> + Row( + modifier.fillMaxWidth(), + verticalAlignment = Alignment.Bottom, + horizontalArrangement = Arrangement.Center + ) { + CurrentRoadNameView( + modifier = modifier, + theme = CardinalNavigationUITheme.roadNameViewTheme, + currentRoadName = roadName + ) + + Spacer(modifier = Modifier.height(8.dp)) + } + } + } +} + +fun navigationViewComponentBuilder(): NavigationViewComponentBuilder { + return NavigationViewComponentBuilder( + instructionsView = @Composable { modifier, navigationUiState -> + CardinalInstructionsView( + modifier, + navigationUiState + ) + }, + progressView = @Composable { modifier, navigationUiState, onTapExit -> + CardinalProgressView( + modifier, + navigationUiState, + onTapExit + ) + }, + roadNameView = @Composable { modifier, roadName, cameraControlState -> + CardinalRoadNameView( + modifier, + roadName, + cameraControlState + ) + }, + ) +} diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/TurnByTurnNavigationScreen.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/navigation/TurnByTurnNavigationScreen.kt similarity index 95% rename from cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/TurnByTurnNavigationScreen.kt rename to cardinal-android/app/src/main/java/earth/maps/cardinal/ui/navigation/TurnByTurnNavigationScreen.kt index 6c107ba0823afdf330ba0953804d4c99e8ff2506..02b1ec0027368cf0daabf388c2af2a60f26609ee 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/TurnByTurnNavigationScreen.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/navigation/TurnByTurnNavigationScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package earth.maps.cardinal.ui.directions +package earth.maps.cardinal.ui.navigation import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box @@ -107,7 +107,10 @@ fun TurnByTurnNavigationScreen( // Only display the navigation view if we have a route if (route != null) { DynamicallyOrientingNavigationView( - styleUrl = styleUrl, modifier = Modifier, viewModel = viewModel + styleUrl = styleUrl, + modifier = Modifier, + viewModel = viewModel, + views = navigationViewComponentBuilder() ) } else { // Show a placeholder or loading state when no route is available diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/TurnByTurnNavigationViewModel.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/navigation/TurnByTurnNavigationViewModel.kt similarity index 96% rename from cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/TurnByTurnNavigationViewModel.kt rename to cardinal-android/app/src/main/java/earth/maps/cardinal/ui/navigation/TurnByTurnNavigationViewModel.kt index 65462f649ac465e3f1d259c2c5add5416d296358..5cb8f7b653e7b07d6cc903f064ff6177e8d59265 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/TurnByTurnNavigationViewModel.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/navigation/TurnByTurnNavigationViewModel.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package earth.maps.cardinal.ui.directions +package earth.maps.cardinal.ui.navigation import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel diff --git a/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/TurnByTurnNavigationViewModelTest.kt b/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/TurnByTurnNavigationViewModelTest.kt index 962f027bdf8f37f629519dad42ce755427d7a352..265cc88d602aac37f155ba18a8c7ce5007fb1ffc 100644 --- a/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/TurnByTurnNavigationViewModelTest.kt +++ b/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/TurnByTurnNavigationViewModelTest.kt @@ -19,6 +19,7 @@ package earth.maps.cardinal.ui.directions import earth.maps.cardinal.routing.FerrostarWrapperRepository +import earth.maps.cardinal.ui.navigation.TurnByTurnNavigationViewModel import io.mockk.mockk import org.junit.Assert.assertEquals import org.junit.Before