diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 26a9e67..435aa85 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -14,8 +14,8 @@ android { applicationId = "com.kouros.navigation" minSdk = 33 targetSdk = 36 - versionCode = 6 - versionName = "0.1.3.6" + versionCode = 7 + versionName = "0.1.3.7" base.archivesName = "navi-$versionName" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -93,6 +93,7 @@ dependencies { implementation(libs.androidx.compose.material3.window.size.class1) implementation(libs.androidx.compose.ui.graphics) implementation(libs.androidx.window) + implementation(libs.androidx.compose.foundation.layout) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) diff --git a/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt b/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt index 849406d..43ade6d 100644 --- a/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt +++ b/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt @@ -13,14 +13,10 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.annotation.RequiresPermission import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.BottomSheetScaffold -import androidx.compose.material3.Card import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text @@ -31,31 +27,23 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableDoubleStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Observer -import androidx.window.layout.WindowMetricsCalculator import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationServices -import com.kouros.android.cars.carappservice.R -import com.kouros.navigation.car.map.BuildingLayer -import com.kouros.navigation.car.map.NavigationImage -import com.kouros.navigation.car.map.RouteLayer -import com.kouros.navigation.data.Constants +import com.kouros.navigation.data.Constants.homeLocation import com.kouros.navigation.data.NavigationRepository import com.kouros.navigation.data.StepData -import com.kouros.navigation.data.nominatim.SearchResult import com.kouros.navigation.model.MockLocation import com.kouros.navigation.model.RouteModel import com.kouros.navigation.model.ViewModel import com.kouros.navigation.ui.theme.NavigationTheme -import com.kouros.navigation.utils.NavigationUtils import com.kouros.navigation.utils.bearing import com.kouros.navigation.utils.calculateZoom import com.kouros.navigation.utils.location @@ -63,18 +51,12 @@ import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import org.maplibre.compose.camera.CameraPosition -import org.maplibre.compose.camera.rememberCameraState import org.maplibre.compose.location.DesiredAccuracy -import org.maplibre.compose.location.LocationTrackingEffect -import org.maplibre.compose.location.UserLocationState +import org.maplibre.compose.location.Location import org.maplibre.compose.location.rememberDefaultLocationProvider import org.maplibre.compose.location.rememberUserLocationState -import org.maplibre.compose.map.MapOptions -import org.maplibre.compose.map.MaplibreMap -import org.maplibre.compose.map.OrnamentOptions -import org.maplibre.compose.sources.getBaseSource -import org.maplibre.compose.style.BaseStyle import org.maplibre.spatialk.geojson.Position import kotlin.time.Duration.Companion.seconds @@ -88,15 +70,19 @@ class MainActivity : ComponentActivity() { var tilt = 50.0 val useMock = true - val instruction: MutableLiveData by lazy { + val stepData: MutableLiveData by lazy { MutableLiveData() } var lastLocation = location(0.0, 0.0) val observer = Observer { newRoute -> - routeModel.startNavigation(newRoute) - routeData.value = routeModel.route.routeGeoJson + if (newRoute.isNotEmpty()) { + routeModel.startNavigation(newRoute) + routeData.value = routeModel.route.routeGeoJson + //mock.setMockLocation(homeLocation.latitude, homeLocation.longitude) + simulate() + } } val cameraPosition = MutableLiveData( CameraPosition( @@ -129,8 +115,8 @@ class MainActivity : ComponentActivity() { if (useMock) { mock = MockLocation(locationManager) mock.setMockLocation( - Constants.homeLocation.latitude, - Constants.homeLocation.longitude + homeLocation.latitude, + homeLocation.longitude ) } enableEdgeToEdge() @@ -139,6 +125,21 @@ class MainActivity : ComponentActivity() { } } + @SuppressLint("MissingPermission") + @Composable + fun CheckPermissionScreen() { + val permissions = listOf( + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + ) + PermissionScreen( + permissions = permissions, + requiredPermissions = listOf(permissions.first()), + onGranted = { + Content() + }, + ) + } @SuppressLint("AutoboxingStateCreation") @OptIn(ExperimentalMaterial3Api::class) @@ -146,6 +147,8 @@ class MainActivity : ComponentActivity() { fun Content() { val scaffoldState = rememberBottomSheetScaffoldState() val snackbarHostState = remember { SnackbarHostState() } + + val scope = rememberCoroutineScope() val locationProvider = rememberDefaultLocationProvider( updateInterval = 0.5.seconds, desiredAccuracy = DesiredAccuracy.Highest @@ -157,7 +160,15 @@ class MainActivity : ComponentActivity() { if (locationState.value != null) { latitude = locationState.value!!.position.latitude } - val step: StepData? by instruction.observeAsState() + val step: StepData? by stepData.observeAsState() + + fun openSheet() { + scope.launch { scaffoldState.bottomSheetState.expand() } + } + + fun closeSheet() { + scope.launch { scaffoldState.bottomSheetState.partialExpand() } + } NavigationTheme { BottomSheetScaffold( @@ -167,7 +178,7 @@ class MainActivity : ComponentActivity() { scaffoldState = scaffoldState, sheetPeekHeight = 128.dp, sheetContent = { - SheetContent(latitude, step) + SheetContent(latitude, step) { closeSheet() } }, ) { innerPadding -> Box( @@ -176,117 +187,35 @@ class MainActivity : ComponentActivity() { .padding(innerPadding), contentAlignment = Alignment.Center, ) { - Map(userLocationState, step) + MapView(applicationContext,userLocationState, step, cameraPosition, routeData, tilt) } } } } @Composable - fun SheetContent(locationState: Double, step: StepData?) { + fun SheetContent(locationState: Double, step: StepData?, closeSheet: () -> Unit) { if (!routeModel.isNavigating()) { - SearchSheet(applicationContext, viewModel, lastLocation) + SearchSheet(applicationContext, viewModel, lastLocation) { closeSheet() } } else { - NavigationSheet( routeModel, step, { simulate() }) - } - // to recomposite SheetContent ! - Text("State $locationState") - } - @Composable - fun NavigationInfo(step: StepData?) { - Card { - Column { - Icon( - painter = painterResource(R.drawable.ic_turn_normal_right), - contentDescription = stringResource(id = R.string.accept_action_title) - ) - if (step != null) { - Text(text = step.instruction, fontSize = 25.sp) - } - } - } - } - - @Composable - fun Map(userLocationState: UserLocationState, step: StepData?) { - Column { - if (step != null) { - NavigationInfo(step) - } - MapView(userLocationState) - } - } - - @Composable - fun MapView(userLocationState: UserLocationState) { - - val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this) - val width = metrics.bounds.width() - val height = metrics.bounds.height() - val paddingValues = PaddingValues(start = 0.dp, top = 350.dp) - - val position: CameraPosition? by cameraPosition.observeAsState() - val route: String? by routeData.observeAsState() - val cameraState = - rememberCameraState( - firstPosition = - CameraPosition( - target = Position( - position!!.target.latitude, - position!!.target.longitude - ), - zoom = 15.0, - ) + NavigationSheet( + routeModel, step!!, + { stopNavigation { closeSheet() } }, + { simulateNavigation() } ) - Box (contentAlignment = Alignment.Center) { - MaplibreMap( - options = MapOptions( - ornamentOptions = - OrnamentOptions(isScaleBarEnabled = false) - ), - cameraState = cameraState, - baseStyle = BaseStyle.Uri(Constants.STYLE), - ) { - getBaseSource(id = "openmaptiles")?.let { tiles -> - if (!NavigationUtils.getBooleanKeyValue( - context = applicationContext, - Constants.SHOW_THREED_BUILDING - ) - ) { - BuildingLayer(tiles) - } - RouteLayer(route, "", position!!.zoom) - } - if (userLocationState.location != null) { - ///PuckState(cameraState, userLocationState) - } - } - - LocationTrackingEffect( - locationState = userLocationState, - ) { - cameraState.animateTo( - finalPosition = CameraPosition( - bearing = position!!.bearing, - zoom = position!!.zoom, - target = position!!.target, - tilt = tilt, - padding = paddingValues - ), - duration = 1.seconds - ) - } - NavigationImage(paddingValues, width, height /6, "") } + // For recomposition! + Text("$locationState", fontSize = 12.sp) } - fun updateLocation(location: org.maplibre.compose.location.Location?) { + fun updateLocation(location: Location?) { if (location != null && lastLocation.latitude != location.position.latitude - && lastLocation.longitude != location.position.longitude) { + && lastLocation.longitude != location.position.longitude + ) { if (routeModel.isNavigating()) { routeModel.updateLocation(lastLocation) - instruction.value = routeModel.currentStep() + stepData.value = routeModel.currentStep() } val currentLocation = location(location.position.longitude, location.position.latitude) val bearing = bearing(lastLocation, currentLocation, cameraPosition.value!!.bearing) @@ -306,6 +235,17 @@ class MainActivity : ComponentActivity() { } } + fun stopNavigation(closeSheet: () -> Unit) { + closeSheet() + routeModel.stopNavigation() + routeData.value = "" + stepData.value = StepData("", 0.0, 0, 0, 0, 0.0) + } + + fun simulateNavigation() { + simulate() + } + private fun checkMockLocationEnabled() { try { // Check if mock location is enabled for this app @@ -330,24 +270,9 @@ class MainActivity : ComponentActivity() { } } - @SuppressLint("MissingPermission") - @Composable - fun CheckPermissionScreen() { - val permissions = listOf( - Manifest.permission.ACCESS_COARSE_LOCATION, - Manifest.permission.ACCESS_FINE_LOCATION, - ) - PermissionScreen( - permissions = permissions, - requiredPermissions = listOf(permissions.first()), - onGranted = { - Content() - }, - ) - } @OptIn(DelicateCoroutinesApi::class) fun simulate() = GlobalScope.async { - for ((i, loc) in routeModel.route.waypoints.withIndex()) { + for ((_, loc) in routeModel.route.waypoints.withIndex()) { if (routeModel.isNavigating()) { mock.setMockLocation(loc[1], loc[0]) delay(1000L) // diff --git a/app/src/main/java/com/kouros/navigation/ui/MapView.kt b/app/src/main/java/com/kouros/navigation/ui/MapView.kt new file mode 100644 index 0000000..67566b8 --- /dev/null +++ b/app/src/main/java/com/kouros/navigation/ui/MapView.kt @@ -0,0 +1,103 @@ +package com.kouros.navigation.ui + +import android.content.Context +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.unit.dp +import androidx.lifecycle.MutableLiveData +import androidx.window.layout.WindowMetricsCalculator +import com.kouros.navigation.car.map.BuildingLayer +import com.kouros.navigation.car.map.NavigationImage +import com.kouros.navigation.car.map.RouteLayer +import com.kouros.navigation.data.Constants +import com.kouros.navigation.data.StepData +import com.kouros.navigation.utils.NavigationUtils +import org.maplibre.compose.camera.CameraPosition +import org.maplibre.compose.camera.rememberCameraState +import org.maplibre.compose.location.LocationTrackingEffect +import org.maplibre.compose.location.UserLocationState +import org.maplibre.compose.map.MapOptions +import org.maplibre.compose.map.MaplibreMap +import org.maplibre.compose.map.OrnamentOptions +import org.maplibre.compose.sources.getBaseSource +import org.maplibre.compose.style.BaseStyle +import org.maplibre.spatialk.geojson.Position +import kotlin.time.Duration.Companion.seconds + +@Composable +fun MapView( + applicationContext: Context, + userLocationState: UserLocationState, + step: StepData?, + cameraPosition: MutableLiveData, + routeData: MutableLiveData, + tilt: Double +) { + + val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(applicationContext) + val width = metrics.bounds.width() + val height = metrics.bounds.height() + val paddingValues = PaddingValues(start = 0.dp, top = 350.dp) + + val position: CameraPosition? by cameraPosition.observeAsState() + val route: String? by routeData.observeAsState() + val cameraState = + rememberCameraState( + firstPosition = + CameraPosition( + target = Position( + position!!.target.latitude, + position!!.target.longitude + ), + zoom = 15.0, + ) + ) + Column { + NavigationInfo(step) + Box(contentAlignment = Alignment.Center) { + MaplibreMap( + options = MapOptions( + ornamentOptions = + OrnamentOptions(isScaleBarEnabled = false) + ), + cameraState = cameraState, + baseStyle = BaseStyle.Uri(Constants.STYLE), + ) { + getBaseSource(id = "openmaptiles")?.let { tiles -> + if (!NavigationUtils.getBooleanKeyValue( + context = applicationContext, + Constants.SHOW_THREED_BUILDING + ) + ) { + BuildingLayer(tiles) + } + RouteLayer(route, "", position!!.zoom) + } + if (userLocationState.location != null) { + ///PuckState(cameraState, userLocationState) + } + } + + LocationTrackingEffect( + locationState = userLocationState, + ) { + cameraState.animateTo( + finalPosition = CameraPosition( + bearing = position!!.bearing, + zoom = position!!.zoom, + target = position!!.target, + tilt = tilt, + padding = paddingValues + ), + duration = 1.seconds + ) + } + NavigationImage(paddingValues, width, height / 6, "") + } + } +} diff --git a/app/src/main/java/com/kouros/navigation/ui/NavigationScreen.kt b/app/src/main/java/com/kouros/navigation/ui/NavigationScreen.kt new file mode 100644 index 0000000..176f443 --- /dev/null +++ b/app/src/main/java/com/kouros/navigation/ui/NavigationScreen.kt @@ -0,0 +1,51 @@ +package com.kouros.navigation.ui + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Card +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.kouros.data.R +import com.kouros.navigation.data.StepData +import com.kouros.navigation.utils.round + +@Composable +fun NavigationInfo(step: StepData?) { + if (step != null && step.instruction.isNotEmpty()) { + Card(modifier = Modifier.padding(top = 60.dp)) { + Column() { + Row { + Icon( + painter = painterResource(step.icon), + contentDescription = stringResource(id = R.string.accept_action_title), + modifier = Modifier.size(48.dp, 48.dp), + ) + Column { + if (step.leftStepDistance < 1000) { + Text(text = "${step.leftStepDistance.toInt()} m", fontSize = 25.sp) + } else { + Text( + text = "${(step.leftStepDistance / 1000).round(1)} km", + fontSize = 25.sp + ) + } + Text(text = step.instruction, fontSize = 20.sp) + } + Icon( + painter = painterResource(step.icon), + contentDescription = stringResource(id = R.string.accept_action_title), + modifier = Modifier.size(48.dp, 48.dp), + ) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kouros/navigation/ui/NavigationSheet.kt b/app/src/main/java/com/kouros/navigation/ui/NavigationSheet.kt index 2df7018..e22f4e2 100755 --- a/app/src/main/java/com/kouros/navigation/ui/NavigationSheet.kt +++ b/app/src/main/java/com/kouros/navigation/ui/NavigationSheet.kt @@ -1,34 +1,45 @@ +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.size import androidx.compose.material3.Button import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.Text +import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp -import com.kouros.android.cars.carappservice.R +import androidx.compose.ui.unit.sp +import com.kouros.data.R import com.kouros.navigation.data.StepData import com.kouros.navigation.model.RouteModel -import kotlinx.coroutines.Deferred +import com.kouros.navigation.utils.formatDateTime +import com.kouros.navigation.utils.round + @Composable fun NavigationSheet( routeModel: RouteModel, - step: StepData?, - simulate: () -> Unit + step: StepData, + stopNavigation: () -> Unit, + simulateNavigation: () -> Unit, ) { + val distance = step.leftDistance.round(1) Column { - //Text("${routeModel.travelLeftTime()}") - if (step != null) - Text("${step.leftDistance / 1000} km") + FlowRow(horizontalArrangement= Arrangement.SpaceEvenly) { + Text(formatDateTime(step.arrivalTime), fontSize = 22.sp) + Spacer(Modifier.size(30.dp)) + Text("$distance km", fontSize = 22.sp) + } HorizontalDivider() - Row() { + FlowRow(horizontalArrangement = Arrangement.SpaceEvenly) { if (routeModel.isNavigating()) { Button(onClick = { - routeModel.stopNavigation() + stopNavigation() }) { Icon( painter = painterResource(id = R.drawable.ic_close_white_24dp), @@ -36,8 +47,9 @@ fun NavigationSheet( modifier = Modifier.size(24.dp, 24.dp), ) } + Spacer(Modifier.size(30.dp)) Button(onClick = { - simulate() + simulateNavigation() }) { Icon( painter = painterResource(id = R.drawable.assistant_navigation_48px), diff --git a/app/src/main/java/com/kouros/navigation/ui/SearchSheet.kt b/app/src/main/java/com/kouros/navigation/ui/SearchSheet.kt index d80ef23..b35a883 100644 --- a/app/src/main/java/com/kouros/navigation/ui/SearchSheet.kt +++ b/app/src/main/java/com/kouros/navigation/ui/SearchSheet.kt @@ -22,8 +22,6 @@ import androidx.compose.material3.SearchBar import androidx.compose.material3.SearchBarDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf @@ -38,7 +36,7 @@ import androidx.compose.ui.semantics.isTraversalGroup import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.traversalIndex import androidx.compose.ui.unit.dp -import com.kouros.android.cars.carappservice.R +import com.kouros.data.R import com.kouros.navigation.data.Place import com.kouros.navigation.data.PlaceColor import com.kouros.navigation.data.nominatim.SearchResult @@ -46,7 +44,12 @@ import com.kouros.navigation.model.ViewModel import com.kouros.navigation.utils.location @Composable -fun SearchSheet(applicationContext: Context, viewModel: ViewModel, location: Location) { +fun SearchSheet( + applicationContext: Context, + viewModel: ViewModel, + location: Location, + closeSheet: () -> Unit +) { val searchResults = mutableListOf() val recentPlaces = viewModel.places.observeAsState() val search = viewModel.searchPlaces.observeAsState() @@ -63,7 +66,9 @@ fun SearchSheet(applicationContext: Context, viewModel: ViewModel, location: Loc searchResults = searchResults, viewModel = viewModel, context = applicationContext, - location = location + location = location, + closeSheet = {closeSheet()} + ) } } @@ -77,7 +82,8 @@ fun SearchSheet(applicationContext: Context, viewModel: ViewModel, location: Loc searchResults = searchResults, viewModel = viewModel, context = applicationContext, - location = location + location = location, + closeSheet = {closeSheet()} ) } } @@ -93,6 +99,7 @@ fun SearchBar( viewModel: ViewModel, context: Context, location: Location, + closeSheet: () -> Unit ) { var expanded by rememberSaveable { mutableStateOf(true) } Box( @@ -121,19 +128,19 @@ fun SearchBar( }, expanded = expanded, onExpandedChange = { expanded = it }, - placeholder = { Text("Suchen") } + placeholder = { Text(context.getString(R.string.search_action_title)) } ) }, expanded = expanded, onExpandedChange = { expanded = it }, ) { if (searchPlaces.isNotEmpty()) { - Text("Recent places") - RecentPlaces(searchPlaces, viewModel, context, location) + Text(context.getString(R.string.recent_destinations)) + RecentPlaces(searchPlaces, viewModel, context, location, closeSheet) } if (searchResults.isNotEmpty()) { Text("Search places") - SearchPlaces(searchResults, viewModel, context, location) + SearchPlaces(searchResults, viewModel, context, location, closeSheet) } } } @@ -149,6 +156,7 @@ private fun SearchPlaces( viewModel: ViewModel, context: Context, location: Location, + closeSheet: () -> Unit ) { val color = remember { PlaceColor } LazyColumn( @@ -171,6 +179,7 @@ private fun SearchPlaces( val toLocation = location(place.lon.toDouble(), place.lat.toDouble()) viewModel.loadRoute(context, location, toLocation) + closeSheet() } .fillMaxWidth() ) @@ -186,7 +195,8 @@ private fun RecentPlaces( recentPlaces: List, viewModel: ViewModel, context: Context, - location: Location + location: Location, + closeSheet: () -> Unit ) { val color = remember { PlaceColor } LazyColumn( @@ -207,6 +217,7 @@ private fun RecentPlaces( .clickable { val toLocation = location(place.longitude, place.latitude) viewModel.loadRoute(context, location, toLocation) + closeSheet() } .fillMaxWidth() ) diff --git a/common/car/build.gradle.kts b/common/car/build.gradle.kts index 1a52ecc..518536a 100644 --- a/common/car/build.gradle.kts +++ b/common/car/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) @@ -27,8 +29,10 @@ android { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } - kotlinOptions { - jvmTarget = "11" + kotlin { + compilerOptions { + jvmTarget = JvmTarget.JVM_11 + } } buildFeatures { compose = true @@ -38,8 +42,7 @@ android { dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.car.app) - - implementation(libs.ui) + implementation(libs.androidx.compose.ui) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.ui) implementation(libs.maplibre.compose) diff --git a/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt b/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt index 9af282a..0a025e0 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/NavigationSession.kt @@ -110,7 +110,6 @@ class NavigationSession : Session(), NavigationScreen.Listener { if ((CarContext.ACTION_NAVIGATE == intent.action)) { val uri = ("http://" + intent.dataString).toUri() val location = Location(LocationManager.GPS_PROVIDER) - screenManager.popToRoot() screenManager.pushForResult( SearchScreen( diff --git a/common/car/src/main/java/com/kouros/navigation/car/map/MapView.kt b/common/car/src/main/java/com/kouros/navigation/car/map/MapView.kt index d560258..b7e6008 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/map/MapView.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/map/MapView.kt @@ -24,7 +24,7 @@ import androidx.compose.ui.text.drawText import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.kouros.android.cars.carappservice.R +import com.kouros.data.R import com.kouros.navigation.data.NavigationColor import com.kouros.navigation.data.RouteColor import com.kouros.navigation.data.SpeedColor diff --git a/common/car/src/main/java/com/kouros/navigation/car/navigation/RouteCarModel.kt b/common/car/src/main/java/com/kouros/navigation/car/navigation/RouteCarModel.kt index 1344a5a..30ff4c0 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/navigation/RouteCarModel.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/navigation/RouteCarModel.kt @@ -28,7 +28,6 @@ import androidx.car.app.navigation.model.Maneuver import androidx.car.app.navigation.model.Step import androidx.car.app.navigation.model.TravelEstimate import androidx.core.graphics.drawable.IconCompat -import com.kouros.android.cars.carappservice.R import com.kouros.navigation.data.Constants.NEXT_STEP_THRESHOLD import com.kouros.navigation.data.ManeuverType import com.kouros.navigation.model.RouteModel @@ -40,34 +39,14 @@ class RouteCarModel() : RouteModel() { /** Returns the current [Step] with information such as the cue text and images. */ fun currentStep(carContext: CarContext): Step { - val maneuver = route.currentManeuver() - val maneuverType = maneuver.type - val stepData = currentStep() - - var routing: (Pair) - routing = if (hasArrived(maneuverType)) { - routingData(maneuverType, carContext) - } else { - routingData(ManeuverType.None.value, carContext) - } - when (stepData.leftDistance) { - in 0.0..NEXT_STEP_THRESHOLD -> { - if (route.currentManeuverIndex < route.maneuvers.size) { - val maneuver = route.nextManeuver() - val maneuverType = maneuver.type - routing = routingData(maneuverType, carContext) - } - } - } - val currentStepCueWithImage: SpannableString = createString(stepData.instruction) val step = Step.Builder(currentStepCueWithImage) .setManeuver( - Maneuver.Builder(routing.first) - .setIcon(routing.second) + Maneuver.Builder(stepData.maneuverType) + .setIcon(createCarIcon(carContext, stepData.icon)) .build() ) .setRoad(destination.street!!) @@ -77,130 +56,40 @@ class RouteCarModel() : RouteModel() { /** Returns the next [Step] with information such as the cue text and images. */ fun nextStep(carContext: CarContext): Step? { - val maneuver = route.nextManeuver() - val maneuverType = maneuver.type - val routing = routingData(maneuverType, carContext) - var text = "" - val distanceLeft = leftStepDistance() - - when (distanceLeft) { - in 0.0..NEXT_STEP_THRESHOLD -> { - return null - } - else -> { - if (maneuver.streetNames != null && maneuver.streetNames!!.isNotEmpty()) { - text = maneuver.streetNames!![0] - } - } - } + val stepData = nextStep() val currentStepCueWithImage: SpannableString = - createString(text) + createString(stepData.instruction) val step = Step.Builder(currentStepCueWithImage) .setManeuver( - Maneuver.Builder(routing.first) - .setIcon(routing.second) + Maneuver.Builder(stepData.maneuverType) + .setIcon(createCarIcon(carContext, stepData.icon)) .build() ) .build() return step } - fun routingData(routeManeuverType: Int, carContext: CarContext): (Pair) { - var type = Maneuver.TYPE_DEPART - var currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_name_change) - when (routeManeuverType) { - ManeuverType.None.value -> { - type = Maneuver.TYPE_STRAIGHT - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_name_change) - } - - ManeuverType.Destination.value, - ManeuverType.DestinationRight.value, - ManeuverType.DestinationLeft.value, - -> { - type = Maneuver.TYPE_DESTINATION - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_destination) - } - - ManeuverType.Right.value -> { - type = Maneuver.TYPE_TURN_NORMAL_RIGHT - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_normal_right) - } - - ManeuverType.Left.value -> { - type = Maneuver.TYPE_TURN_NORMAL_LEFT - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_normal_left) - } - - ManeuverType.RampRight.value -> { - type = Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_slight_right) - } - - ManeuverType.RampLeft.value -> { - type = Maneuver.TYPE_TURN_NORMAL_LEFT - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_normal_left) - } - - ManeuverType.ExitRight.value -> { - type = Maneuver.TYPE_TURN_SLIGHT_RIGHT - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_slight_right) - } - - ManeuverType.StayRight.value -> { - type = Maneuver.TYPE_KEEP_RIGHT - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_name_change) - } - - ManeuverType.StayLeft.value -> { - type = Maneuver.TYPE_KEEP_LEFT - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_name_change) - } - - ManeuverType.RoundaboutEnter.value -> { - type = Maneuver.TYPE_ROUNDABOUT_ENTER_CCW - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_roundabout_ccw) - } - - ManeuverType.RoundaboutExit.value -> { - type = Maneuver.TYPE_ROUNDABOUT_EXIT_CCW - currentTurnIcon = createCarIcon(carContext, R.drawable.ic_roundabout_ccw) - } - } - maneuverType = type - return Pair(type, currentTurnIcon) - } - - fun hasArrived(type: Int): Boolean { - return type == ManeuverType.DestinationRight.value - || maneuverType == ManeuverType.Destination.value - || maneuverType == ManeuverType.DestinationLeft.value - } - fun travelEstimate(): TravelEstimate { val timeLeft = travelLeftTime() - // Calculate the time to destination from the current time. - val nowUtcMillis = System.currentTimeMillis() val timeToDestinationMillis = TimeUnit.SECONDS.toMillis(timeLeft.toLong()) - val leftDistance = travelLeftDistance() val displayUnit = if (leftDistance > 1.0) { Distance.UNIT_KILOMETERS } else { Distance.UNIT_METERS } + val arivalTime = DateTimeWithZone.create( + arrivalTime(), + TimeZone.getTimeZone("Europe/Berlin") + ) return TravelEstimate.Builder( // The estimated distance to the destination. Distance.create( leftDistance, displayUnit ), // Arrival time at the destination with the destination time zone. - - DateTimeWithZone.create( - nowUtcMillis + timeToDestinationMillis, - TimeZone.getTimeZone("Europe/Berlin") - ) + arivalTime ) .setRemainingTimeSeconds( TimeUnit.MILLISECONDS.toSeconds( diff --git a/common/car/src/main/java/com/kouros/navigation/car/screen/DisplaySettings.kt b/common/car/src/main/java/com/kouros/navigation/car/screen/DisplaySettings.kt index 930b1ef..f8b011d 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/screen/DisplaySettings.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/screen/DisplaySettings.kt @@ -10,7 +10,7 @@ import androidx.car.app.model.ListTemplate import androidx.car.app.model.Row import androidx.car.app.model.Template import androidx.car.app.model.Toggle -import com.kouros.android.cars.carappservice.R +import com.kouros.data.R import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue import com.kouros.navigation.utils.NavigationUtils.setBooleanKeyValue diff --git a/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationScreen.kt b/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationScreen.kt index b71d260..abfc9b7 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationScreen.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationScreen.kt @@ -25,7 +25,7 @@ import androidx.car.app.notification.CarPendingIntent import androidx.car.app.suggestion.model.Suggestion import androidx.core.graphics.drawable.IconCompat import androidx.lifecycle.Observer -import com.kouros.android.cars.carappservice.R +import com.kouros.data.R import com.kouros.navigation.car.NavigationCarAppService import com.kouros.navigation.car.SurfaceRenderer import com.kouros.navigation.car.navigation.RouteCarModel diff --git a/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationSettings.kt b/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationSettings.kt index ec7e0de..1e36110 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationSettings.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/screen/NavigationSettings.kt @@ -9,7 +9,7 @@ import androidx.car.app.model.ListTemplate import androidx.car.app.model.Row import androidx.car.app.model.Template import androidx.car.app.model.Toggle -import com.kouros.android.cars.carappservice.R +import com.kouros.data.R import com.kouros.navigation.data.Constants.AVOID_MOTORWAY import com.kouros.navigation.data.Constants.AVOID_TOLLWAY import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue diff --git a/common/car/src/main/java/com/kouros/navigation/car/screen/PlaceListScreen.kt b/common/car/src/main/java/com/kouros/navigation/car/screen/PlaceListScreen.kt index 6108f27..b0f76eb 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/screen/PlaceListScreen.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/screen/PlaceListScreen.kt @@ -18,7 +18,7 @@ import androidx.car.app.model.Row import androidx.car.app.model.Template import androidx.core.graphics.drawable.IconCompat import androidx.lifecycle.Observer -import com.kouros.android.cars.carappservice.R +import com.kouros.data.R import com.kouros.navigation.car.SurfaceRenderer import com.kouros.navigation.car.navigation.RouteCarModel import com.kouros.navigation.data.Constants diff --git a/common/car/src/main/java/com/kouros/navigation/car/screen/RoutePreviewScreen.kt b/common/car/src/main/java/com/kouros/navigation/car/screen/RoutePreviewScreen.kt index 5793fad..1985c7d 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/screen/RoutePreviewScreen.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/screen/RoutePreviewScreen.kt @@ -39,7 +39,7 @@ import androidx.car.app.navigation.model.MapController import androidx.car.app.navigation.model.MapWithContentTemplate import androidx.core.graphics.drawable.IconCompat import androidx.lifecycle.Observer -import com.kouros.android.cars.carappservice.R +import com.kouros.data.R import com.kouros.navigation.car.SurfaceRenderer import com.kouros.navigation.car.navigation.NavigationMessage import com.kouros.navigation.car.navigation.RouteCarModel diff --git a/common/car/src/main/java/com/kouros/navigation/car/screen/SearchScreen.kt b/common/car/src/main/java/com/kouros/navigation/car/screen/SearchScreen.kt index 1e763bc..185168b 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/screen/SearchScreen.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/screen/SearchScreen.kt @@ -14,7 +14,7 @@ import androidx.car.app.model.SearchTemplate.SearchCallback import androidx.car.app.model.Template import androidx.core.graphics.drawable.IconCompat import androidx.lifecycle.Observer -import com.kouros.android.cars.carappservice.R +import com.kouros.data.R import com.kouros.navigation.car.SurfaceRenderer import com.kouros.navigation.data.Category import com.kouros.navigation.data.Constants diff --git a/common/car/src/main/java/com/kouros/navigation/car/screen/SettingsScreen.kt b/common/car/src/main/java/com/kouros/navigation/car/screen/SettingsScreen.kt index c67824f..46fca1d 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/screen/SettingsScreen.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/screen/SettingsScreen.kt @@ -15,9 +15,7 @@ */ package com.kouros.navigation.car.screen -import android.content.Context import androidx.car.app.CarContext -import androidx.car.app.CarToast import androidx.car.app.Screen import androidx.car.app.model.Action import androidx.car.app.model.Header @@ -25,10 +23,7 @@ import androidx.car.app.model.ItemList import androidx.car.app.model.ListTemplate import androidx.car.app.model.Row import androidx.car.app.model.Template -import androidx.car.app.model.Toggle -import androidx.core.content.edit -import com.kouros.android.cars.carappservice.R -import com.kouros.navigation.car.NavigationSession +import com.kouros.data.R /** A screen demonstrating selectable lists. */ class SettingsScreen( diff --git a/common/car/src/main/res/drawable-navexposed/assistant_navigation_48px.xml b/common/car/src/main/res/drawable-navexposed/assistant_navigation_48px.xml deleted file mode 100644 index 1077be0..0000000 --- a/common/car/src/main/res/drawable-navexposed/assistant_navigation_48px.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/common/car/src/main/res/drawable/arrow_right_turn.png b/common/car/src/main/res/drawable/arrow_right_turn.png deleted file mode 100644 index 6b93cec..0000000 Binary files a/common/car/src/main/res/drawable/arrow_right_turn.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/arrow_straight.png b/common/car/src/main/res/drawable/arrow_straight.png deleted file mode 100644 index 7367dd4..0000000 Binary files a/common/car/src/main/res/drawable/arrow_straight.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/assistant_navigation_48px.xml b/common/car/src/main/res/drawable/assistant_navigation_48px.xml deleted file mode 100644 index 1077be0..0000000 --- a/common/car/src/main/res/drawable/assistant_navigation_48px.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/common/car/src/main/res/drawable/baseline_assistant_navigation_24.xml b/common/car/src/main/res/drawable/baseline_assistant_navigation_24.xml deleted file mode 100644 index 3b7031f..0000000 --- a/common/car/src/main/res/drawable/baseline_assistant_navigation_24.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - diff --git a/common/car/src/main/res/drawable/baseline_navigation_24.xml b/common/car/src/main/res/drawable/baseline_navigation_24.xml deleted file mode 100644 index 65886f8..0000000 --- a/common/car/src/main/res/drawable/baseline_navigation_24.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/drawable/ic_close_white_24dp.xml b/common/car/src/main/res/drawable/ic_close_white_24dp.xml deleted file mode 100644 index 5832c5a..0000000 --- a/common/car/src/main/res/drawable/ic_close_white_24dp.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/drawable/ic_delete_background.xml b/common/car/src/main/res/drawable/ic_delete_background.xml deleted file mode 100644 index ca3826a..0000000 --- a/common/car/src/main/res/drawable/ic_delete_background.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/common/car/src/main/res/drawable/ic_delete_foreground.xml b/common/car/src/main/res/drawable/ic_delete_foreground.xml deleted file mode 100644 index e153c58..0000000 --- a/common/car/src/main/res/drawable/ic_delete_foreground.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/drawable/ic_favorite_filled_white_24dp.xml b/common/car/src/main/res/drawable/ic_favorite_filled_white_24dp.xml deleted file mode 100644 index d3df144..0000000 --- a/common/car/src/main/res/drawable/ic_favorite_filled_white_24dp.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/drawable/ic_favorite_white_24dp.xml b/common/car/src/main/res/drawable/ic_favorite_white_24dp.xml deleted file mode 100644 index 7709015..0000000 --- a/common/car/src/main/res/drawable/ic_favorite_white_24dp.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/drawable/ic_launcher_background.xml b/common/car/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index ca3826a..0000000 --- a/common/car/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/common/car/src/main/res/drawable/ic_pan_24.xml b/common/car/src/main/res/drawable/ic_pan_24.xml deleted file mode 100644 index 1dfeed1..0000000 --- a/common/car/src/main/res/drawable/ic_pan_24.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - diff --git a/common/car/src/main/res/drawable/ic_place_white_24dp.xml b/common/car/src/main/res/drawable/ic_place_white_24dp.xml deleted file mode 100644 index 1ba39ce..0000000 --- a/common/car/src/main/res/drawable/ic_place_white_24dp.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/drawable/ic_roundabout_ccw.png b/common/car/src/main/res/drawable/ic_roundabout_ccw.png deleted file mode 100644 index 478f371..0000000 Binary files a/common/car/src/main/res/drawable/ic_roundabout_ccw.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_roundabout_cw.png b/common/car/src/main/res/drawable/ic_roundabout_cw.png deleted file mode 100644 index c5e824e..0000000 Binary files a/common/car/src/main/res/drawable/ic_roundabout_cw.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_search_black36dp.png b/common/car/src/main/res/drawable/ic_search_black36dp.png deleted file mode 100644 index cebcea1..0000000 Binary files a/common/car/src/main/res/drawable/ic_search_black36dp.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_stop.png b/common/car/src/main/res/drawable/ic_stop.png deleted file mode 100644 index 42c7530..0000000 Binary files a/common/car/src/main/res/drawable/ic_stop.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_destination.png b/common/car/src/main/res/drawable/ic_turn_destination.png deleted file mode 100644 index 4dde74e..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_destination.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_fork_left.png b/common/car/src/main/res/drawable/ic_turn_fork_left.png deleted file mode 100644 index 1bb58b4..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_fork_left.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_fork_right.png b/common/car/src/main/res/drawable/ic_turn_fork_right.png deleted file mode 100644 index 35dd540..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_fork_right.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_merge_symmetrical.png b/common/car/src/main/res/drawable/ic_turn_merge_symmetrical.png deleted file mode 100644 index 5925a8c..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_merge_symmetrical.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_name_change.png b/common/car/src/main/res/drawable/ic_turn_name_change.png deleted file mode 100644 index 363fc89..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_name_change.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_normal_left.png b/common/car/src/main/res/drawable/ic_turn_normal_left.png deleted file mode 100644 index 572a48c..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_normal_left.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_normal_right.png b/common/car/src/main/res/drawable/ic_turn_normal_right.png deleted file mode 100644 index b9cc652..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_normal_right.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_sharp_left.png b/common/car/src/main/res/drawable/ic_turn_sharp_left.png deleted file mode 100644 index 8b29193..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_sharp_left.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_sharp_right.png b/common/car/src/main/res/drawable/ic_turn_sharp_right.png deleted file mode 100644 index f9adbb6..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_sharp_right.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_slight_left.png b/common/car/src/main/res/drawable/ic_turn_slight_left.png deleted file mode 100644 index 0a0d417..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_slight_left.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_slight_right.png b/common/car/src/main/res/drawable/ic_turn_slight_right.png deleted file mode 100644 index bfcb32b..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_slight_right.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_u_turn_left.png b/common/car/src/main/res/drawable/ic_turn_u_turn_left.png deleted file mode 100644 index e37bbbe..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_u_turn_left.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_turn_u_turn_right.png b/common/car/src/main/res/drawable/ic_turn_u_turn_right.png deleted file mode 100644 index 9f26af1..0000000 Binary files a/common/car/src/main/res/drawable/ic_turn_u_turn_right.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/ic_zoom_in_24.xml b/common/car/src/main/res/drawable/ic_zoom_in_24.xml deleted file mode 100644 index 36d3282..0000000 --- a/common/car/src/main/res/drawable/ic_zoom_in_24.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/drawable/ic_zoom_out_24.xml b/common/car/src/main/res/drawable/ic_zoom_out_24.xml deleted file mode 100644 index 089d265..0000000 --- a/common/car/src/main/res/drawable/ic_zoom_out_24.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/drawable/lanes.png b/common/car/src/main/res/drawable/lanes.png deleted file mode 100644 index 4374cb2..0000000 Binary files a/common/car/src/main/res/drawable/lanes.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/navigation.png b/common/car/src/main/res/drawable/navigation.png deleted file mode 100644 index 7ebe828..0000000 Binary files a/common/car/src/main/res/drawable/navigation.png and /dev/null differ diff --git a/common/car/src/main/res/drawable/navigation_48px.xml b/common/car/src/main/res/drawable/navigation_48px.xml deleted file mode 100644 index e87c0a6..0000000 --- a/common/car/src/main/res/drawable/navigation_48px.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/common/car/src/main/res/drawable/outline_bookmark_add_24.xml b/common/car/src/main/res/drawable/outline_bookmark_add_24.xml deleted file mode 100644 index 93aeae9..0000000 --- a/common/car/src/main/res/drawable/outline_bookmark_add_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/drawable/outline_bookmark_added_24.xml b/common/car/src/main/res/drawable/outline_bookmark_added_24.xml deleted file mode 100644 index 3960836..0000000 --- a/common/car/src/main/res/drawable/outline_bookmark_added_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/drawable/settings_24px.xml b/common/car/src/main/res/drawable/settings_24px.xml deleted file mode 100644 index 4bcd4aa..0000000 --- a/common/car/src/main/res/drawable/settings_24px.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/common/car/src/main/res/drawable/turn_right_48px.xml b/common/car/src/main/res/drawable/turn_right_48px.xml deleted file mode 100644 index 730ed7d..0000000 --- a/common/car/src/main/res/drawable/turn_right_48px.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/common/car/src/main/res/drawable/turn_right_48px1.xml b/common/car/src/main/res/drawable/turn_right_48px1.xml deleted file mode 100644 index 730ed7d..0000000 --- a/common/car/src/main/res/drawable/turn_right_48px1.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/common/car/src/main/res/mipmap-anydpi-v26/ic_delete.xml b/common/car/src/main/res/mipmap-anydpi-v26/ic_delete.xml deleted file mode 100644 index c76661e..0000000 --- a/common/car/src/main/res/mipmap-anydpi-v26/ic_delete.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/common/car/src/main/res/mipmap-anydpi-v26/ic_delete_round.xml b/common/car/src/main/res/mipmap-anydpi-v26/ic_delete_round.xml deleted file mode 100644 index c76661e..0000000 --- a/common/car/src/main/res/mipmap-anydpi-v26/ic_delete_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/common/car/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/common/car/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index bbd3e02..0000000 --- a/common/car/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/common/car/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/common/car/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index bbd3e02..0000000 --- a/common/car/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/common/car/src/main/res/mipmap-hdpi/ic_delete.webp b/common/car/src/main/res/mipmap-hdpi/ic_delete.webp deleted file mode 100644 index d991c89..0000000 Binary files a/common/car/src/main/res/mipmap-hdpi/ic_delete.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-hdpi/ic_delete_round.webp b/common/car/src/main/res/mipmap-hdpi/ic_delete_round.webp deleted file mode 100644 index 9bb57ba..0000000 Binary files a/common/car/src/main/res/mipmap-hdpi/ic_delete_round.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-hdpi/ic_launcher.webp b/common/car/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index da24c35..0000000 Binary files a/common/car/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/common/car/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index 2850a90..0000000 Binary files a/common/car/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-mdpi/ic_delete.webp b/common/car/src/main/res/mipmap-mdpi/ic_delete.webp deleted file mode 100644 index 51311ea..0000000 Binary files a/common/car/src/main/res/mipmap-mdpi/ic_delete.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-mdpi/ic_delete_round.webp b/common/car/src/main/res/mipmap-mdpi/ic_delete_round.webp deleted file mode 100644 index 27bd006..0000000 Binary files a/common/car/src/main/res/mipmap-mdpi/ic_delete_round.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-mdpi/ic_launcher.webp b/common/car/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 8042972..0000000 Binary files a/common/car/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/common/car/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index 940caf5..0000000 Binary files a/common/car/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xhdpi/ic_delete.webp b/common/car/src/main/res/mipmap-xhdpi/ic_delete.webp deleted file mode 100644 index 4e2031e..0000000 Binary files a/common/car/src/main/res/mipmap-xhdpi/ic_delete.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xhdpi/ic_delete_round.webp b/common/car/src/main/res/mipmap-xhdpi/ic_delete_round.webp deleted file mode 100644 index d5c635e..0000000 Binary files a/common/car/src/main/res/mipmap-xhdpi/ic_delete_round.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xhdpi/ic_launcher.webp b/common/car/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index c52ae69..0000000 Binary files a/common/car/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/common/car/src/main/res/mipmap-xhdpi/ic_launcher_round.webp deleted file mode 100644 index 56b8e2b..0000000 Binary files a/common/car/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xxhdpi/ic_delete.webp b/common/car/src/main/res/mipmap-xxhdpi/ic_delete.webp deleted file mode 100644 index 3cbf6d0..0000000 Binary files a/common/car/src/main/res/mipmap-xxhdpi/ic_delete.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xxhdpi/ic_delete_round.webp b/common/car/src/main/res/mipmap-xxhdpi/ic_delete_round.webp deleted file mode 100644 index aa08b89..0000000 Binary files a/common/car/src/main/res/mipmap-xxhdpi/ic_delete_round.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/common/car/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 284db5a..0000000 Binary files a/common/car/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/common/car/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp deleted file mode 100644 index 2f729db..0000000 Binary files a/common/car/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xxxhdpi/ic_delete.webp b/common/car/src/main/res/mipmap-xxxhdpi/ic_delete.webp deleted file mode 100644 index 1aae1c1..0000000 Binary files a/common/car/src/main/res/mipmap-xxxhdpi/ic_delete.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xxxhdpi/ic_delete_round.webp b/common/car/src/main/res/mipmap-xxxhdpi/ic_delete_round.webp deleted file mode 100644 index b5a8d51..0000000 Binary files a/common/car/src/main/res/mipmap-xxxhdpi/ic_delete_round.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/common/car/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index 9b5e24c..0000000 Binary files a/common/car/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/common/car/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/common/car/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 56a171b..0000000 Binary files a/common/car/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/common/car/src/main/res/values-de/strings.xml b/common/car/src/main/res/values-de/strings.xml deleted file mode 100644 index d7acf7b..0000000 --- a/common/car/src/main/res/values-de/strings.xml +++ /dev/null @@ -1,308 +0,0 @@ - - - - - "Beenden" - "Aktualisieren" - "Schließen" - "Zugriff gewähren" - "Standortermittlung aktivieren" - "Ignorieren" - "Stopp" - "Mehr" - "Anrufen" - "Optionen" - "Suchen" - "Aktiviert" - "Deaktiviert" - "An" - "Aus" - "Einstellungen" - "Annehmen" - "Ablehnen" - "OK" - "Auslösen" - "Arbeitsweg" - "Abmelden" - "Ja" - "Nein" - "Herangezoomt" - "Herausgezoomt" - "Favoriten" - "Kein Favorit!" - "Navigation angefragt" - "Ausgewählte Route" - "Sichtbare Routen" - "Einstellungen angeklickt" - "Aktion „Geparkt“" - "„Mehr“ angeklickt" - "Standortermittlung erlauben, um aktuellen Standort anzuzeigen" - "Navigieren" - "Wählen" - "Adresse" - "Smartphone" - "Fehler beim Starten der Navigation" - "Fehler beim Starten des Telefons" - "Einstellungen für die Anzeige" - "Paket wurde nicht gefunden." - "Alle Berechtigungen wurden erteilt. Du kannst sie in den Einstellungen deaktivieren." - "Die App benötigt Zugriff auf die folgenden Berechtigungen:\n" - "Berechtigungen über das Smartphone-Display erteilen" - "Berechtigungen zur Standortermittlung auf Gerät aktivieren" - "Standortermittlung auf dem Smartphone-Bildschirm aktivieren" - "Erforderliche Berechtigungen" - "Demo der Berechtigungsanfrage" - "Bildschirm zum Stornieren der Reservierung" - "Reservierung wurde storniert" - "Ergebnisdemo" - "Diese App wurde nicht für ein Ergebnis gestartet" - "Diese App wurde aufgerufen, um Ergebnisse aus %s zu erhalten. Wähle das Ergebnis aus, das an den Anrufer zurückgesendet werden soll." - "Angekommen!" - "Benachrichtigung senden" - "Benachrichtigungen starten" - "Benachrichtigungen deaktivieren" - "Benachrichtigung" - "Wichtigkeit" - "Kategorie" - "Aktiv" - "Standard" - "Hoch" - "Gering" - "Unbekannt" - "Benachrichtigungsdemo" - "Verschiedene Demos" - "Navigationsdemo" - "Demo für „Angekommen“" - "Demo des Kreuzungsbildes" - "Demos der Navigationsvorlage" - "Demo der Kartenvorlage mit Bereich" - "Demo der Kartenvorlage mit Liste" - "Benachrichtigung beginnen" - "Benachrichtigung deaktivieren" - "Demo der Navigationsbenachrichtigung" - "Geradeaus fahren" - "Rechts abbiegen" - "Die 520 nehmen" - "Tankstelle" - "Kurze Route" - "Weniger Verkehr" - "Carpool-Spur-fähig" - "Lange Route" - "Weiter, um die Navigation zu starten" - "Weiter zur Route" - "Route" - Neue Route Berechnung - "Demo der Navigationsvorlage für Ortslisten" - "Demo der Routenvorschauvorlage" - "Demo der Benachrichtigungsvorlage" - "Demo der Navigationsvorlage nur mit Karte" - "Navigationsdemos" - "Blitzer noch da?" - "Vor 10 Minuten gemeldet" - "Keine Berechtigung für Mautkarte." - "Keine Berechtigung für Akkustand." - "Keine Berechtigung für Geschwindigkeit." - "Keine Berechtigung für Kilometerstand." - "Keine Berechtigung für Status des Elektrofahrzeugs." - "Keine Berechtigung für Beschleunigungsmesser." - "Keine Berechtigung für Gyroskop." - "Keine Berechtigung für Kompass." - "Keine Berechtigung für Auto-Hardware-Standort." - "Mautinformationen werden abgerufen." - "Akkustand wird abgerufen." - "Geschwindigkeit wird abgerufen." - "Kilometerstand wird abgerufen." - "Status des Elektrofahrzeugs wird abgerufen." - "Beschleunigungsmesser wird abgerufen." - "Gyroskop wird abgerufen." - "Kompass wird abgerufen." - "Standort wird abgerufen." - "Status der Mautkarte" - "Niedriger Akkustand" - "Bereich" - "Kraftstoff" - "Akku" - "Geschwindigkeit anzeigen" - "Rohgeschwindigkeit" - "Einheit" - "Kilometerzähler" - "Ladeanschluss des Elektrofahrzeugs verbunden" - "Ladeanschluss des Elektrofahrzeugs ist offen" - "Beschleunigungsmesser" - "Gyroskop" - "Kompass" - "Standort der Auto-Hardware" - "Keine Aktion möglich" - "Zweiter Eintrag" - "Dritter Eintrag" - "Vierter Eintrag" - "Der fünfte Eintrag hat einen langen Titel" - "Der sechste Eintrag hat einen langen Titel" - "Demo der Rastervorlage" - "Titel für „Nur geparkt“" - "Mehr Text für „Nur geparkt“." - "Angeklickte Zeile" - "Erste Textzeile" - "Zweite Textzeile" - "Dieser Subtext kann im uneingeschränkten Modus (z. B. Parkmodus, eingeschränkter Modus für niedrige Geschwindigkeit) vollständig angezeigt werden. Im eingeschränkten Modus (z. B. Fahrmodus) wird er jedoch nach zwei Zeilen abgeschnitten. Zu Testzwecken ist dieser Subtext extrem lang." - "Titel" - "Demo für Listenvorlage" - "Demo der langen Nachrichtenvorlage" - "Dein Host unterstützt keine lange Nachrichtenvorlage" - "Inkompatibler Host" - "Keine Orte" - "Bitte lies unsere ""Nutzungsbedingungen" - "Google Log-in" - "PIN nutzen" - "QR-Code" - "Dein Host unterstützt keine Anmeldevorlage" - "Inkompatibler Host" - "E-Mail" - "Anmelden" - "Anmeldedaten eingeben" - "Der Nutzername muss eine gültige E-Mail-Adresse sein" - "Der Nutzername muss mindestens %s Zeichen enthalten" - "Ungültiges Passwort" - "Passwort" - "Nutzername" - "Gib diese PIN auf deinem Telefon ein" - "Zum Anmelden QR-Code scannen" - "Über Google anmelden" - "Schließe mit dieser Schaltfläche dein Google Log-in ab" - "Du bist angemeldet!" - "Anmeldung abgeschlossen" - "Anmeldungsvorlagendemo" - "Tab-Vorlage – Demos" - "Tab-Vorlage – Demo" - "Tab „Nachrichten“" - "Tab „Bereich“" - "Tab „Liste“" - "Tab „Raster“ mit langem Tab-Titel" - "Tab „Suche“" - "Tab wird geladen" - "Tab-Vorlage – Demo wird geladen" - "Tab-Vorlage – Demo „Keine Tabs“" - "Für einen unbekannten Host können keine Bilder angezeigt werden" - "Symbol" - "Demo der Contentanbietersymbole" - "Symboldemo" - "Das App-Symbol" - "Ein Vektor-Drawable ohne Färbung" - "Ein Vektor-Drawable mit einer Färbung" - "Ein Vektor-Drawable mit einem App-Designattribut für die Farbe" - "Eine PNG wurde als Ressource gesendet" - "Eine PNG-Datei, als Bitmap gesendet" - "Nur ein Titel" - "Titel mit App-Symbol" - "Titel mit Bild für Ressourcen-ID" - "Titel mit SVG-Bild" - "Farbiger Sekundärtext" - "Titel mit mehreren Zeilen Sekundärtext" - "Du darfst irren, und irren, und irren – aber immer weniger, und weniger, und weniger." - "– Piet Hein" - "Demo der Zeilen" - "Demos für Text und Symbole" - "Demo der Zeilen mit Text und Symbolen" - "Demo der Optionsfeldlisten" - "Demo der auswählbaren Listen" - "Option 1" - "Option 2" - "Option 3" - "Zeile mit Optionsfeld" - "Zeile mit Optionsfeld und Symbol" - "Zeile mit Optionsfeld, Symbol und farbigem Text" - "Zusätzlicher Text" - "Beispiel für auswählbare Liste" - "Demo der Aufgabenbeschränkung" - "Hierdurch wird die maximale Anzahl an Schritten überschritten und du gelangst zu einem neuen Bildschirm." - "Aufgabe: Schritt %1$d von %2$d" - "Klicken, um fortzufahren" - "Bitte rufe die verschiedenen Vorlagen auf und achte darauf, dass sich das Auto im Fahrmodus befindet" - "Demo der Ein-/Aus-Schaltfläche" - "Test der Ein-/Aus-Schaltfläche" - "Zustandsorientierte Änderungen sind erlaubt" - "Test der Ein-/Aus-Schaltfläche aktivieren" - "Klicke diese Option an, um den Test der Ein-/Aus-Schaltfläche zu aktivieren" - "Test der Ein-/Aus-Schaltfläche" - "Zustandsorientierte Änderungen sind erlaubt" - "Bildtest" - "Bildänderungen sind erlaubt" - "Zusätzliche Daten" - "Updates beim Zurückgehen erlaubt." - "Test der Ein-/Aus-Schaltfläche aktiviert" - "Test der Ein-/Aus-Schaltfläche deaktiviert" - "Demo der sekundären Aktion und der Dekoration" - "Test für sekundäre Aktion" - "Nur die sekundäre Aktion kann ausgewählt werden" - "Dekorationstest" - "Sekundäre Aktionen und Dekoration" - "Zeile mit sekundären Aktionen und Dekoration mit einem sehr langen Titel" - "Auch diese Zeile kann ausgewählt werden" - Eintrag gelöscht - "Zeile mit der primären Aktion ist ausgewählt" - "Demo für Elementliste mit Abschnitten" - "Liste 1" - "Liste 2" - "Subtext unter jeder Liste" - "Leere Liste – Demo" - "Die Liste ist leer" - "Demos der verschiedenen Vorlagen" - "Demos anzeigen" - "Demo der Layoutvorlagen" - "Demo der Rastervorlagen" - "Bildschirm für Voice Access-Demo" - "Nutzerinteraktionen" - "Demos zur Berechtigungsanfrage" - "Anwendungs-Overflow-Validator" - "Bitte teste die folgenden Vorlagen, wenn du" - "das Fahrzeug vom Park- in den Fahrmodus umschaltest" - "Berechtigungsgruppe" - "Berechtigungsgruppe für die Showcase App" - "Zugriff auf genauen Standort" - "Berechtigung für Zugriff auf den genauen Standort" - "Zugriff auf ungefähren Standort" - "Berechtigung für Zugriff auf den ungefähren Standort" - "Zugriff für Audioaufnahmen" - "Berechtigung für Zugriff für Audioaufnahmen" - "Gefärbter Ressourcenvektor" - "Bitmap-Infobild" - "Farbige Textmarkierung" - "Bitmap-Bild" - "Textlabel" - "Demo: Parken im Vergleich zu Fahren" - "Displays in Autos." - "Navigation" - Anzeige - "3D Gebäude" - "Laden deaktiviert" - "Ladebildschirm" - "Schieberegler zum Hinzufügen/Entfernen von Farben" - "Kartenvorlage mit Ein-/Aus-Schaltflächen" - "Mautstraßen meiden" - "Routenoptionen" - "Autobahnen meiden" - "Fähren meiden" - "Kartenbezogene Demos" - "Demos von Karten mit Inhalten" - "Karte mit Demo der Nachrichtenvorlage" - "Demo einer Karte mit Rastervorlage" - Routen - Letzte Ziele - Kontakte - Jetzt losfahren - diff --git a/common/car/src/main/res/values/attrs.xml b/common/car/src/main/res/values/attrs.xml deleted file mode 100644 index d6b0be2..0000000 --- a/common/car/src/main/res/values/attrs.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - diff --git a/common/car/src/main/res/values/strings.xml b/common/car/src/main/res/values/strings.xml deleted file mode 100644 index fa2c99d..0000000 --- a/common/car/src/main/res/values/strings.xml +++ /dev/null @@ -1,415 +0,0 @@ - - - Navigation - - - Exit - Refresh - Close - Grant Access - Enable Location - Cancel - Stop - More - Call - Options - Search - Checked - Unchecked - On - Off - Settings - Accept - Reject - OK - Throw - Commute - Sign out - Yes - No - - - Zoomed in - Zoomed out - Favorites - Not a favorite! - Navigation Requested - Selected route - Visible routes - Clicked Settings - Parked action - Clicked More - Grant location Permission to see current location - - - - Navigate - Dial - Address - Phone - - - Failure starting navigation - Failure starting dialer - - Display settings - - - Package Not found. - All permissions have been granted. Please revoke permissions from Settings. - The app needs access to the following permissions:\n - Grant Permission on the phone screen - Enable Location Permissions on device - Enable location on the phone screen - Required Permissions - Request Permission Demo - - - Cancel Reservation Screen - Reservation canceled - - - Result demo - This app was not started for result - This app was called for result from %s. Please select the result to send back to the caller - - - Arrived! - - - Roy st 520 - I5 Aurora Ave N - - - Send a notification - Start notifications - Stop notifications - Notification - Importance - Category - Ongoing - Default - High - Low - Unknown - Notification Demo - - - Misc Demos - - - Navigating Demo - Arrived Demo - Junction Image Demo - Navigation Template Demos - - - Map Template with Pane Demo - Map Template with List Demo - - - Start Notification - Stop Notification - Navigation Notification Demo - - - Go Straight - Turn Right - Take 520 - Gas Station - - Short route - Less busy - HOV friendly - Long route - Continue to start navigation - Continue to route - Routes - New Route calculation - - - Place List Navigation Template Demo - Route Preview Template Demo - Notification Template Demo - Navigation Template with map only Demo - Navigation Demos - Still a speed trap? - Reported 10m ago - - - No TollCard Permission. - No EnergyLevel Permission. - No Speed Permission. - No Mileage Permission. - No EV status Permission. - No Accelerometer Permission. - No Gyroscope Permission. - No Compass Permission. - No CarHardwareLocation Permission. - Fetching Toll information. - Fetching Energy Level. - Fetching Speed. - Fetching Mileage. - Fetching EV status. - Fetching Accelerometer. - Fetching Gyroscope. - Fetching Compass. - Fetching Location. - Toll card state - Low energy - Range - Fuel - Battery - Display Speed - Raw Speed - Unit - Odometer - Ev Charge Port Connected - Ev Charge Port Open - Accelerometer - Gyroscope - Compass - Car Hardware Location - - - Non-actionable - Second Item - Third Item - Fourth Item - Fifth Item has a long title set - Sixth Item has a long title set - Grid Template Demo - - - Parked Only Title - More Parked only text. - Clicked row - First line of text - Second line of text - This subtext can fully display in unrestricted mode (ex. parking mode, restricted low speed mode). But this will truncate to only two lines while in restricted mode (ex. driving mode). For testing purposes, this subtext is super super super super super long - Title - List Template Demo - - - Long Message Template Demo - Lorem ipsum dolor sit amet, consectetur adipiscing elit. \nAliquam laoreet ac metus eu commodo. Sed a congue diam, sed dictum lectus. Nam nec\ntristique dolor, quis sodales arcu. Etiam at metus eu nulla auctor varius. \nInteger dolor lorem, placerat sit amet lacus in, imperdiet semper dui. Vestibulum \nante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; \nQuisque gravida fermentum egestas.\n\n\n\nUt ut sodales mi. Aenean porta vel ipsum sed lacinia. Morbi odio ipsum, hendrerit \neu est et, sollicitudin finibus diam. Nunc sit amet felis elit. Orci varius \nnatoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed \nvestibulum, tellus a rutrum auctor, diam arcu vestibulum purus, nec mollis ligula \nnisi in nisi. Donec sem tortor, pharetra sed fermentum sit amet, ullamcorper nec \nsapien. Aliquam risus arcu, porttitor eu dui nec, vulputate tempus libero. \nCurabitur sit amet tristique orci. Suspendisse et odio tempus, tempus turpis quis,\n euismod est.\n\n\n\nVestibulum mauris ante, luctus viverra nisi eget, blandit facilisis nulla. \nPhasellus ex lorem, semper in vestibulum nec, aliquet vel elit. Aliquam vitae \nligula nec enim dictum lobortis. Sed varius turpis quis nisi tempus varius. Sed \nnon sollicitudin magna, at mattis tortor. Curabitur quis ligula eget lorem mattis \ntincidunt et in sapien. Curabitur a elit nisi. Aliquam ex arcu, hendrerit eget \nturpis vitae, bibendum vulputate nibh. Fusce vitae ex aliquet, tristique magna eu,\n vulputate dui. Aenean tempor viverra tortor non pharetra. Pellentesque convallis \nnec risus a auctor. Praesent non sem non eros tincidunt ullamcorper efficitur non \nlacus.\n\n\n\nSuspendisse accumsan ultricies egestas. Aenean leo ligula, congue ac erat eu, \nlobortis ultricies lorem. Nulla finibus, arcu sed tincidunt lobortis, magna justo \nrutrum ligula, et mattis felis turpis vel ex. Morbi ac auctor ex, at bibendum sem.\n Vestibulum a tortor iaculis, viverra felis vitae, lobortis est. Duis sit amet \ncondimentum sem. Ut molestie, dolor pretium imperdiet maximus, enim orci porta \nquam, id gravida enim nunc vitae lacus. Pellentesque habitant morbi tristique \nsenectus et netus et malesuada fames ac turpis egestas. Nullam vel justo eu risus \nlobortis dignissim sit amet ullamcorper nulla. Donec finibus cursus purus \nporttitor pellentesque.\n\n\n\nDonec at vehicula ante. Suspendisse rutrum nisl quis metus faucibus lacinia. \nVestibulum eros sapien, eleifend nec accumsan a, interdum sed nisi. Aenean posuere\n ultrices lorem non pharetra. Nulla non porta ligula. Maecenas at elit diam. \nNullam gravida augue et semper eleifend. Fusce venenatis ac arcu et luctus. Mauris\n ultricies urna non dui interdum, vel hendrerit est aliquam. Fusce id dictum leo, \nfringilla egestas ipsum. - Your host doesn\'t support Long Message template - Incompatible host - - - No Places - - - - Please review our terms of service - Google sign-in - Use PIN - QR Code - Your host doesn\'t support Sign In template - Incompatible host - Email - Sign in - Enter your credentials - User name must be a valid email address - User name must be at least %s characters long - Invalid password - password - Username - Type this PIN in your phone - Scan QR Code to sign in - Sign in with Google - Use this button to complete your Google sign-in - You are signed in! - Sign in completed - Sign In Template Demo - - - Tab Template Demos - Tab Template Demo - Message Tab - Pane Tab - List Tab - Grid Tab with Long Tab Title - Search Tab - Loading Tab - Tab Template Loading Demo - Tab Template No Tabs Demo - - - Images cannot be displayed for an unknown host - Icon - Content Provider Icons Demo - - - Icons Demo - The app icon - A vector drawable, without a tint - A vector drawable, with a tint - A vector drawable, with an app\'s theme attribute for its color - A PNG, sent as a resource - A PNG, sent as a bitmap - - - Just a title - Title with app icon - Title with resource ID image - Title with SVG image - Colored secondary text - Title with multiple secondary text lines - Err and err and err again, but less and less and less. - - Piet Hein - Rows Demo - - - Text and Icons Demos - Rows with Text and Icons Demo - - - Radio Button Lists Demo - Selectable Lists Demo - Option 1 - Option 2 - Option 3 - Row with Radio Button - Row with Radio Button and Icon - Row with Radio Button and Icon and Colored Text - Some additional text - Sample selectable list - - - Task Restriction Demo - This will overflow the step count, and lead you to a new screen. - Task step %1$d of %2$d - Click to go forward - Please visit the different templates and ensure the car is in driving mode - - - Toggle Button Demo - Toggle test - Stateful changes are allowed - Enable Toggle Test - Check this one to enable the toggle test - Toggle test - Stateful changes are allowed - Image test - Image changes are allowed - Additional Data - Updates allowed on back operations. - Toggle Test Enabled - Toggle Test Disabled - - - Secondary Action and Decoration Demo - Secondary Action Test - Only the secondary action can be selected - Decoration Test - Secondary Actions and Decoration - Row with Secondary Actions and Decoration with a really long title - The row can also be selected - Place deleted - Row primary action is selected - - - - Sectioned Item List Demo - List 1 - List 2 - Subtext under each list - - - Empty List Demo - The list is empty - - - Misc Templates Demos - CAL API Level: %d - Showcase Demos - Template Layout Demos - Grid Template Demos - - - Voice Access Demo Screen - User Interactions - Request Permissions Demos - - - Application Overflow Validator - Please test the following templates while changing - the vehicle from parked to driving state - - - Permission Group - Permission Group for Showcase App - Access to Fine Location - Permission for Access to Fine Location - Access to Coarse Location - Permission for Access to Coarse Location - Access to Record Audio - Permission for Access to Record Audio - - - Google Kirkland - 747 6th St South, Kirkland, WA 98033 - Tinted resource vector - +14257395600 - Google Bellevue - 1120 112th Ave NE, Bellevue, WA 98004 - Image resource bitmap - +14252301301 - Google South Lake Union - 1021 Valley St, Seattle, WA 98109 - Colored text marker - +12065311800 - Google Seattle - 601 N 34th St, Seattle, WA 98103 - Image bitmap - +12068761800 - 1600 Amphitheatre Pkwy, Mountain View, CA 94043 - +16502530000 - Google Bothell - 11831 North Creek Pkwy, Bothell, WA 98011 - Seward Park - 5900 Lake Washington Blvd S, Seattle, WA 98118 - Luther Burbank Park - 2040 84th Ave SE, Mercer Island, WA 98040 - Heritage Park - 111 Waverly Way, Kirkland, WA 98033 - Text label - n/a - - Parking Vs Driving Demo - Cluster Displays in cars! - Navigation - Display - 3D Building - Loading disabled - Loading screen - Toggle to add/remove color - Map Template with Toggles - Avoid tolls - Route options - Avoid highways - Avoid ferry - Map Demos - Map With Content Demos - Map With Message Template Demo - Map With Grid Template Demo - Routes - Recent - Contacts - Drive now - diff --git a/common/car/src/main/res/values/styles.xml b/common/car/src/main/res/values/styles.xml deleted file mode 100644 index d983543..0000000 --- a/common/car/src/main/res/values/styles.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - diff --git a/common/car/src/main/res/xml/automotive_app_desc.xml b/common/car/src/main/res/xml/automotive_app_desc.xml deleted file mode 100644 index cec730a..0000000 --- a/common/car/src/main/res/xml/automotive_app_desc.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/common/data/build.gradle.kts b/common/data/build.gradle.kts index a43bdf1..a23b530 100644 --- a/common/data/build.gradle.kts +++ b/common/data/build.gradle.kts @@ -1,4 +1,5 @@ import org.gradle.kotlin.dsl.annotationProcessor +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { @@ -8,8 +9,6 @@ plugins { kotlin("kapt") } - - android { namespace = "com.kouros.data" compileSdk = 36 @@ -33,13 +32,14 @@ android { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } - kotlinOptions { - jvmTarget = "11" + kotlin { + compilerOptions { + jvmTarget = JvmTarget.JVM_11 + } } } dependencies { - implementation(libs.android.sdk.turf) implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) implementation(libs.material) @@ -47,6 +47,9 @@ dependencies { implementation(libs.koin.core) implementation(libs.koin.android) implementation(libs.koin.compose.viewmodel) + implementation(libs.androidx.car.app) + implementation(libs.android.sdk.turf) + // objectbox implementation(libs.objectbox.kotlin) diff --git a/common/data/src/main/java/com/kouros/navigation/data/Data.kt b/common/data/src/main/java/com/kouros/navigation/data/Data.kt index 1ba89aa..e5a5b1e 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/Data.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/Data.kt @@ -16,19 +16,12 @@ package com.kouros.navigation.data -import android.R import android.location.Location import android.location.LocationManager import android.net.Uri -import com.google.gson.GsonBuilder -import com.kouros.navigation.data.valhalla.Maneuvers -import com.kouros.navigation.data.valhalla.ValhallaJson -import com.kouros.navigation.utils.NavigationUtils.createGeoJson -import com.kouros.navigation.utils.NavigationUtils.decodePolyline import io.objectbox.annotation.Entity import io.objectbox.annotation.Id import kotlinx.serialization.Serializable -import org.maplibre.geojson.Point data class Category( val id: String, @@ -61,7 +54,16 @@ data class ContactData( data class StepData ( var instruction: String, - var leftDistance: Double, + + var leftStepDistance: Double, + + var maneuverType: Int, + + var icon: Int, + + var arrivalTime : Long, + + var leftDistance: Double ) diff --git a/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt b/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt index 3265233..b6702fc 100644 --- a/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt +++ b/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt @@ -2,7 +2,12 @@ package com.kouros.navigation.model import android.location.Location import android.location.LocationManager +import androidx.car.app.navigation.model.Maneuver +import androidx.car.app.navigation.model.Step +import com.kouros.data.R +import com.kouros.navigation.data.Constants import com.kouros.navigation.data.Constants.NEXT_STEP_THRESHOLD +import com.kouros.navigation.data.ManeuverType import com.kouros.navigation.data.Place import com.kouros.navigation.data.Route import com.kouros.navigation.data.StepData @@ -10,6 +15,7 @@ import com.kouros.navigation.utils.location import org.maplibre.geojson.FeatureCollection import org.maplibre.geojson.Point import org.maplibre.turf.TurfMeasurement +import java.util.concurrent.TimeUnit import kotlin.math.roundToInt open class RouteModel() { @@ -44,25 +50,51 @@ open class RouteModel() { navigating = true } - - private fun createCenterLocation(): Location { - - val future = TurfMeasurement.center(FeatureCollection.fromJson(route.routeGeoJson)) - val point = future.geometry() as Point - return location(point.longitude(), point.latitude()) + fun stopNavigation() { + route.clear() + navigating = false + currentShapeIndex = 0 + distanceToStepEnd = 0F + beginIndex = 0 + endIndex = 0 } + /** + * Calculates the geographic center of the route's GeoJSON data. + * + * @return A [Location] object representing the center point. + * @throws IllegalStateException if the calculated center does not have valid Point geometry. + */ + private fun createCenterLocation(): Location { + // 1. Create a FeatureCollection from the raw GeoJSON string. + val featureCollection = FeatureCollection.fromJson(route.routeGeoJson) + + // 2. Calculate the center feature of the collection. + val centerFeature = TurfMeasurement.center(featureCollection) + + // 3. Safely access and cast the geometry, throwing an informative error if it fails. + val centerPoint = centerFeature.geometry() as? Point + ?: throw IllegalStateException("Center of GeoJSON is not a valid Point.") + + // 4. Create and return the Location object. + return location(centerPoint.longitude(), centerPoint.latitude()) + } + + /** + * The remaining distance to the step, rounded to the nearest 10 units. + */ val currentDistance: Double - /** Returns the current [Step] with information such as the cue text and images. */ get() { - return ((leftStepDistance()).roundToInt().toDouble() / 10.0).roundToInt() * 10.0 + // This is a more direct way to round to the nearest multiple of 10. + return (leftStepDistance() / 10.0).roundToInt() * 10.0 } + + fun updateLocation(location: Location) { var nearestDistance = 100000.0f - route.currentManeuverIndex = -1 - // find maneuver - for ((i, maneuver) in route.maneuvers.withIndex()) { + for (i in route.currentManeuverIndex.. { - if (route.currentManeuverIndex < route.maneuvers.size) { - val maneuver = route.nextManeuver() - if (maneuver.streetNames != null && maneuver.streetNames.isNotEmpty()) { - text = maneuver.streetNames[0] - } - } - } - } - return StepData(text, distanceStepLeft) - } - /** Calculates the index in a maneuver. */ private fun calculateCurrentShapeIndex( beginShapeIndex: Int, @@ -105,7 +113,7 @@ open class RouteModel() { location: Location ) { var nearestLocation = 100000.0f - for (i in beginShapeIndex..endShapeIndex) { + for (i in currentShapeIndex..endShapeIndex) { val waypoint = Location(LocationManager.GPS_PROVIDER) waypoint.longitude = route.waypoints[i][0] waypoint.latitude = route.waypoints[i][1] @@ -131,6 +139,97 @@ open class RouteModel() { } } + fun currentStep(): StepData { + // Determine if we should display the current or the next maneuver + val distanceToNextStep = leftStepDistance() + val isNearNextManeuver = distanceToNextStep in 0.0..NEXT_STEP_THRESHOLD + val shouldAdvance = + isNearNextManeuver && route.currentManeuverIndex < (route.maneuvers.size - 1) + + // Get the single, correct maneuver for this state + val relevantManeuver = if (shouldAdvance) { + route.nextManeuver() // This advances the route's state + } else { + route.currentManeuver() + } + + // Safely get the street name from the maneuver + val streetName = relevantManeuver.streetNames?.firstOrNull() ?: "" + + // Determine the maneuver type and corresponding icon + val maneuverType = if (hasArrived(relevantManeuver.type)) { + relevantManeuver.type + } else { + ManeuverType.None.value + } + val maneuverIconPair = maneuverIcon(maneuverType) + + // Construct and return the final StepData object + return StepData( + streetName, + distanceToNextStep, + maneuverIconPair.first, + maneuverIconPair.second, + arrivalTime(), + travelLeftDistance() + ) + } + + + fun currentStepx(): StepData { + val maneuver = route.currentManeuver() + var text = "" + if (maneuver.streetNames != null && maneuver.streetNames.isNotEmpty()) { + text = maneuver.streetNames[0] + } + val distanceStepLeft = leftStepDistance() + when (distanceStepLeft) { + in 0.0..Constants.NEXT_STEP_THRESHOLD -> { + if (route.currentManeuverIndex < route.maneuvers.size) { + val maneuver = route.nextManeuver() + if (maneuver.streetNames != null && maneuver.streetNames.isNotEmpty()) { + text = maneuver.streetNames[0] + } + } + } + } + val type = if (hasArrived(maneuverType)) { + maneuver.type + } else { + ManeuverType.None.value + } + var routing: (Pair) = maneuverIcon(type) + when (distanceStepLeft) { + in 0.0..NEXT_STEP_THRESHOLD -> { + if (route.currentManeuverIndex < route.maneuvers.size) { + val maneuver = route.nextManeuver() + val maneuverType = maneuver.type + routing = maneuverIcon(maneuverType) + } + } + } + return StepData(text, distanceStepLeft, routing.first, routing.second, arrivalTime(), travelLeftDistance()) + } + + fun nextStep(): StepData { + val maneuver = route.nextManeuver() + val maneuverType = maneuver.type + val distanceLeft = leftStepDistance() + var text = "" + + when (distanceLeft) { + in 0.0..NEXT_STEP_THRESHOLD -> { + } + else -> { + if (maneuver.streetNames != null && maneuver.streetNames!!.isNotEmpty()) { + text = maneuver.streetNames[0] + } + } + } + val routing: (Pair) = maneuverIcon(maneuverType) + return StepData(text, distanceLeft, routing.first, routing.second, arrivalTime(), travelLeftDistance()) + } + private fun calculateDistance( beginShapeIndex: Int, endShapeIndex: Int, @@ -138,9 +237,7 @@ open class RouteModel() { ): Float { var nearestLocation = 100000.0f for (i in beginShapeIndex..endShapeIndex) { - val polylineLocation = Location(LocationManager.GPS_PROVIDER) - polylineLocation.longitude = route.waypoints[i][0] - polylineLocation.latitude = route.waypoints[i][1] + val polylineLocation = location(route.waypoints[i][0], route.waypoints[i][1]) val distance: Float = location.distanceTo(polylineLocation) if (distance < nearestLocation) { nearestLocation = distance @@ -165,12 +262,21 @@ open class RouteModel() { return timeLeft } + fun arrivalTime(): Long { + val timeLeft = travelLeftTime() + // Calculate the time to destination from the current time. + val nowUtcMillis = System.currentTimeMillis() + val timeToDestinationMillis = + TimeUnit.SECONDS.toMillis(timeLeft.toLong()) + return nowUtcMillis + timeToDestinationMillis + } + /** Returns the current [Step] left distance in m. */ fun leftStepDistance(): Double { val maneuver = route.currentManeuver() var leftDistance = maneuver.length if (endIndex > 0) { - leftDistance = distanceToStepEnd.toDouble() + leftDistance = (distanceToStepEnd / 1000).toDouble() } return leftDistance * 1000 } @@ -192,6 +298,72 @@ open class RouteModel() { return leftDistance } + fun maneuverIcon(routeManeuverType: Int): (Pair) { + var type = Maneuver.TYPE_DEPART + var currentTurnIcon = R.drawable.ic_turn_name_change + when (routeManeuverType) { + ManeuverType.None.value -> { + type = Maneuver.TYPE_STRAIGHT + currentTurnIcon = R.drawable.ic_turn_name_change + } + + ManeuverType.Destination.value, + ManeuverType.DestinationRight.value, + ManeuverType.DestinationLeft.value, + -> { + type = Maneuver.TYPE_DESTINATION + currentTurnIcon = R.drawable.ic_turn_destination + } + + ManeuverType.Right.value -> { + type = Maneuver.TYPE_TURN_NORMAL_RIGHT + currentTurnIcon = R.drawable.ic_turn_normal_right + } + + ManeuverType.Left.value -> { + type = Maneuver.TYPE_TURN_NORMAL_LEFT + currentTurnIcon = R.drawable.ic_turn_normal_left + } + + ManeuverType.RampRight.value -> { + type = Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT + currentTurnIcon = R.drawable.ic_turn_slight_right + } + + ManeuverType.RampLeft.value -> { + type = Maneuver.TYPE_TURN_NORMAL_LEFT + currentTurnIcon = R.drawable.ic_turn_normal_left + } + + ManeuverType.ExitRight.value -> { + type = Maneuver.TYPE_TURN_SLIGHT_RIGHT + currentTurnIcon = R.drawable.ic_turn_slight_right + } + + ManeuverType.StayRight.value -> { + type = Maneuver.TYPE_KEEP_RIGHT + currentTurnIcon = R.drawable.ic_turn_name_change + } + + ManeuverType.StayLeft.value -> { + type = Maneuver.TYPE_KEEP_LEFT + currentTurnIcon = R.drawable.ic_turn_name_change + } + + ManeuverType.RoundaboutEnter.value -> { + type = Maneuver.TYPE_ROUNDABOUT_ENTER_CCW + currentTurnIcon = R.drawable.ic_roundabout_ccw + } + + ManeuverType.RoundaboutExit.value -> { + type = Maneuver.TYPE_ROUNDABOUT_EXIT_CCW + currentTurnIcon = R.drawable.ic_roundabout_ccw + } + } + maneuverType = type + return Pair(type, currentTurnIcon) + } + fun isNavigating(): Boolean { return navigating } @@ -200,12 +372,9 @@ open class RouteModel() { return arrived } - fun stopNavigation() { - route.clear() - navigating = false - currentShapeIndex = 0 - distanceToStepEnd = 0F - beginIndex = 0 - endIndex = 0 + fun hasArrived(type: Int): Boolean { + return type == ManeuverType.DestinationRight.value + || maneuverType == ManeuverType.Destination.value + || maneuverType == ManeuverType.DestinationLeft.value } } \ No newline at end of file diff --git a/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt b/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt index 27cce56..1857253 100644 --- a/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt +++ b/common/data/src/main/java/com/kouros/navigation/utils/NavigationUtils.kt @@ -13,10 +13,17 @@ import org.maplibre.geojson.Point import org.maplibre.turf.TurfMisc import java.lang.Math.toDegrees import java.lang.Math.toRadians +import java.time.LocalDateTime +import java.time.ZoneId +import java.time.ZoneOffset +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle import kotlin.math.asin import kotlin.math.atan2 import kotlin.math.cos import kotlin.math.pow +import kotlin.math.roundToInt import kotlin.math.sin @@ -191,4 +198,16 @@ fun location(longitude : Double, latitude: Double): Location { location.longitude = longitude location.latitude = latitude return location +} + +fun formatDateTime(time: Long): String { + val dateFormatter = DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT) + val dateTime = LocalDateTime.ofEpochSecond(time / 1000, 0, ZoneOffset.UTC) + val zdt = ZonedDateTime.of(dateTime, ZoneId.of("Europe/Berlin")) + return zdt.format(dateFormatter) +} + +fun Double.round(numFractionDigits: Int): Double { + val factor = 10.0.pow(numFractionDigits.toDouble()) + return (this * factor).roundToInt() / factor } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 411fbe0..b65dd53 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,30 +13,31 @@ junitVersion = "1.3.0" espressoCore = "3.7.0" kotlinxSerializationJson = "1.9.0" lifecycleRuntimeKtx = "2.10.0" -composeBom = "2025.11.01" +composeBom = "2025.12.00" appcompat = "1.7.1" material = "1.13.0" carApp = "1.7.0" -androidx-car = "1.7.0-beta01" +androidx-car = "1.7.0" objectboxKotlin = "5.0.1" objectboxProcessor = "5.0.1" -ui = "1.9.5" +ui = "1.10.0" material3 = "1.4.0" -runtimeLivedata = "1.9.5" -foundation = "1.9.5" +runtimeLivedata = "1.10.0" +foundation = "1.10.0" maplibre-composeMaterial3 = "0.12.2" maplibre-compose = "0.12.1" playServicesLocation = "21.3.0" -runtime = "1.9.5" +runtime = "1.10.0" accompanist = "0.37.3" -uiVersion = "1.9.5" -uiText = "1.9.5" +uiVersion = "1.10.0" +uiText = "1.10.0" navigationCompose = "2.9.6" -uiToolingPreview = "1.9.5" -uiTooling = "1.9.5" +uiToolingPreview = "1.10.0" +uiTooling = "1.10.0" material3WindowSizeClass = "1.4.0" uiGraphics = "1.10.0" window = "1.5.1" +foundationLayout = "1.10.0" [libraries] @@ -59,7 +60,6 @@ material = { group = "com.google.android.material", name = "material", version.r androidx-car-app = { group = "androidx.car.app", name = "app", version.ref = "carApp" } objectbox-kotlin = { module = "io.objectbox:objectbox-kotlin", version.ref = "objectboxKotlin" } objectbox-processor = { module = "io.objectbox:objectbox-processor", version.ref = "objectboxProcessor" } -ui = { group = "androidx.compose.ui", name = "ui", version.ref = "ui" } maplibre-compose = { module = "org.maplibre.compose:maplibre-compose", version.ref = "maplibre-compose" } maplibre-composeMaterial3 = { module = "org.maplibre.compose:maplibre-compose-material3", version = "maplibre-composeMaterial3" } androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" } @@ -77,6 +77,7 @@ androidx-compose-material3-window-size-class1 = { group = "androidx.compose.mate androidx-app-automotive = { module = "androidx.car.app:app-automotive", version.ref = "androidx-car" } androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics", version.ref = "uiGraphics" } androidx-window = { group = "androidx.window", name = "window", version.ref = "window" } +androidx-compose-foundation-layout = { group = "androidx.compose.foundation", name = "foundation-layout", version.ref = "foundationLayout" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }