From 758856e9d9b4c2ef38f55cdea2b58f5875701827 Mon Sep 17 00:00:00 2001 From: mitulsheth Date: Tue, 17 Mar 2026 23:11:33 +0530 Subject: [PATCH 1/4] fix(message): This itinerary is too long --- .../cardinal/data/RouteStateRepository.kt | 8 +++- .../ui/directions/DirectionUiError.kt | 19 ++++++++ .../ui/directions/DirectionsScreen.kt | 19 ++++++++ .../ui/directions/DirectionsViewModel.kt | 3 ++ .../app/src/main/res/values/strings.xml | 1 + .../ui/directions/DirectionsViewModelTest.kt | 47 +++++++++++++++++++ 6 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt index dbbd580..649a84e 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt @@ -19,6 +19,7 @@ package earth.maps.cardinal.data import androidx.annotation.VisibleForTesting +import earth.maps.cardinal.ui.directions.DirectionUiError import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -29,6 +30,7 @@ data class RouteState( val isLoading: Boolean = false, val error: String? = null, val selectedRouteIndex: Int? = null, + val directionError: DirectionUiError? = null, ) class RouteStateRepository { @@ -40,7 +42,7 @@ class RouteStateRepository { } fun setRoutes(routes: List) { - _routeState.value = _routeState.value.copy(routes = routes, isLoading = false, error = null) + _routeState.value = _routeState.value.copy(routes = routes, isLoading = false, error = null, directionError = null) } fun selectRoute(index: Int) { @@ -51,6 +53,10 @@ class RouteStateRepository { _routeState.value = _routeState.value.copy(isLoading = false, error = error) } + fun setDirectionError(directionError: DirectionUiError?) { + _routeState.value = _routeState.value.copy(isLoading = false, directionError = directionError) + } + fun clear() { _routeState.value = RouteState() } diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt new file mode 100644 index 0000000..cfc9d8c --- /dev/null +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt @@ -0,0 +1,19 @@ +package earth.maps.cardinal.ui.directions + +import android.media.MediaParser +import uniffi.ferrostar.ParsingException + +sealed class DirectionUiError { + object DistanceExceeded : DirectionUiError() + data class Unknown(val message: String?) : DirectionUiError() +} + +object DirectionCodes { + const val DISTANCE_EXCEEDED = "DistanceExceeded" +} + +fun ParsingException.InvalidStatusCode.toRouteError(): DirectionUiError = + when (this.code) { + DirectionCodes.DISTANCE_EXCEEDED -> DirectionUiError.DistanceExceeded + else -> DirectionUiError.Unknown(this.message) + } \ No newline at end of file diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt index fc42a7b..69a650f 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt @@ -70,6 +70,7 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.error import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.max @@ -499,6 +500,24 @@ private fun NonTransitRouteResults( ) } + routeState.directionError != null -> { + val message = when (routeState.directionError) { + DirectionUiError.DistanceExceeded -> stringResource(string.long_itinerary_error_message) + is DirectionUiError.Unknown -> routeState.directionError.message?.let { + stringResource(string.directions_error, routeState.directionError.message) + } + } + message?.let { + Text( + text = it, + color = MaterialTheme.colorScheme.error, + modifier = Modifier + .fillMaxWidth() + .padding(dimensionResource(dimen.padding)) + ) + } + } + routeState.routes.isNotEmpty() -> { FerrostarRouteResults( routeState = routeState, diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsViewModel.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsViewModel.kt index 20a3594..9dc09b7 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsViewModel.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsViewModel.kt @@ -55,6 +55,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import uniffi.ferrostar.GeographicCoordinate +import uniffi.ferrostar.ParsingException import uniffi.ferrostar.UserLocation import uniffi.ferrostar.Waypoint import uniffi.ferrostar.WaypointKind @@ -173,6 +174,8 @@ class DirectionsViewModel @Inject constructor( } routeStateRepository.setRoutes(routes) + } catch (invalidStatusCode: ParsingException.InvalidStatusCode) { + routeStateRepository.setDirectionError(invalidStatusCode.toRouteError()) } catch (e: Exception) { Log.e(TAG, "Error while fetching route", e) routeStateRepository.setError( diff --git a/cardinal-android/app/src/main/res/values/strings.xml b/cardinal-android/app/src/main/res/values/strings.xml index cceb14e..9a3ab14 100644 --- a/cardinal-android/app/src/main/res/values/strings.xml +++ b/cardinal-android/app/src/main/res/values/strings.xml @@ -155,6 +155,7 @@ Routing Profile Routing Mode Directions + This itinerary is too long From To Profile: %1$s diff --git a/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/DirectionsViewModelTest.kt b/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/DirectionsViewModelTest.kt index 4c9b73e..912af31 100644 --- a/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/DirectionsViewModelTest.kt +++ b/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/DirectionsViewModelTest.kt @@ -22,6 +22,7 @@ import earth.maps.cardinal.routing.RouteRepository import earth.maps.cardinal.transit.TransitousService import io.mockk.coEvery import io.mockk.coVerify +import io.mockk.coVerifyOrder import io.mockk.mockk import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow @@ -38,6 +39,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner +import uniffi.ferrostar.ParsingException import uniffi.ferrostar.Route import kotlin.time.ExperimentalTime @@ -87,6 +89,7 @@ class DirectionsViewModelTest { coEvery { mockRouteStateRepository.setRoutes(any()) } returns Unit coEvery { mockPlanStateRepository.setPlanResponse(any()) } returns Unit coEvery { mockRouteStateRepository.setError(any()) } returns Unit + coEvery { mockRouteStateRepository.setDirectionError(any()) } returns Unit coEvery { mockPlanStateRepository.setError(any()) } returns Unit // Mock routing profile repository @@ -272,6 +275,50 @@ class DirectionsViewModelTest { coVerify { mockRouteStateRepository.setError(errorMessage) } } + @Test + fun `fetchDirectionsIfNeeded should handle too long error`() = runTest { + val fromPlace = Place( + id = "1", + name = "New York", + latLng = LatLng(40.7128, -74.0060), + address = null + ) + val toPlace = Place( + id = "2", + name = "London", + latLng = LatLng(51.5074, -0.1278), + address = null + ) + + val mockFerrostarWrapper = mockk() + coEvery { mockFerrostarWrapperRepository.driving } returns mockFerrostarWrapper + + val distanceExceededException = ParsingException.InvalidStatusCode( + code = DirectionCodes.DISTANCE_EXCEEDED, + description = "Distance exceeded" + ) + coEvery { + mockFerrostarWrapper.core.getRoutes(any(), any()) + } throws distanceExceededException + + val state = viewModel.routeState.value + assertEquals(RouteState(), state) + assertFalse(state.isLoading) + assertTrue(state.routes.isEmpty()) + + viewModel.updateFromPlace(fromPlace) + viewModel.updateToPlace(toPlace) + + advanceUntilIdle() + + assertFalse(state.isLoading) + assertTrue(state.routes.isEmpty()) + coVerifyOrder { + mockRouteStateRepository.setLoading(true) + mockRouteStateRepository.setDirectionError(DirectionUiError.DistanceExceeded) + } + } + @Test fun `fetchDirectionsIfNeeded should not fetch if fromPlace is null`() = runTest { val toPlace = Place( -- GitLab From 690bf1beb9865ea3b4609434b60a999c19dfac97 Mon Sep 17 00:00:00 2001 From: mitulsheth Date: Tue, 17 Mar 2026 23:14:15 +0530 Subject: [PATCH 2/4] fix(message): This itinerary is too long - removed unused imports --- .../earth/maps/cardinal/ui/directions/DirectionUiError.kt | 2 -- .../earth/maps/cardinal/ui/directions/DirectionsScreen.kt | 4 ---- .../earth/maps/cardinal/ui/directions/DirectionsViewModel.kt | 1 - 3 files changed, 7 deletions(-) diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt index cfc9d8c..d8364d9 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt @@ -1,6 +1,4 @@ package earth.maps.cardinal.ui.directions - -import android.media.MediaParser import uniffi.ferrostar.ParsingException sealed class DirectionUiError { diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt index 69a650f..52c39d5 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt @@ -25,11 +25,9 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.ime import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.safeDrawing @@ -70,10 +68,8 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.error import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.max import androidx.navigation.NavController import earth.maps.cardinal.R.dimen import earth.maps.cardinal.R.drawable diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsViewModel.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsViewModel.kt index 9dc09b7..4d027df 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsViewModel.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsViewModel.kt @@ -50,7 +50,6 @@ import earth.maps.cardinal.ui.core.Screen import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -- GitLab From d57bc11c3cff04d6cbfb8203f7de7ae049d7e0ce Mon Sep 17 00:00:00 2001 From: mitulsheth Date: Wed, 18 Mar 2026 12:58:01 +0530 Subject: [PATCH 3/4] fix(ai-review): This itinerary is too long - Resolve AI Code review --- .../maps/cardinal/data/RouteStateRepository.kt | 2 +- .../cardinal/ui/directions/DirectionsScreen.kt | 18 ++++++++---------- .../app/src/main/res/values/strings.xml | 1 + .../ui/directions/DirectionsViewModelTest.kt | 3 ++- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt index 649a84e..5626ae2 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt @@ -54,7 +54,7 @@ class RouteStateRepository { } fun setDirectionError(directionError: DirectionUiError?) { - _routeState.value = _routeState.value.copy(isLoading = false, directionError = directionError) + _routeState.value = _routeState.value.copy(isLoading = false, directionError = directionError, error = null) } fun clear() { diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt index 52c39d5..099d416 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt @@ -501,17 +501,15 @@ private fun NonTransitRouteResults( DirectionUiError.DistanceExceeded -> stringResource(string.long_itinerary_error_message) is DirectionUiError.Unknown -> routeState.directionError.message?.let { stringResource(string.directions_error, routeState.directionError.message) - } - } - message?.let { - Text( - text = it, - color = MaterialTheme.colorScheme.error, - modifier = Modifier - .fillMaxWidth() - .padding(dimensionResource(dimen.padding)) - ) + } ?: stringResource(string.unknown_error) } + Text( + text = message, + color = MaterialTheme.colorScheme.error, + modifier = Modifier + .fillMaxWidth() + .padding(dimensionResource(dimen.padding)) + ) } routeState.routes.isNotEmpty() -> { diff --git a/cardinal-android/app/src/main/res/values/strings.xml b/cardinal-android/app/src/main/res/values/strings.xml index 9a3ab14..08f8fee 100644 --- a/cardinal-android/app/src/main/res/values/strings.xml +++ b/cardinal-android/app/src/main/res/values/strings.xml @@ -156,6 +156,7 @@ Routing Mode Directions This itinerary is too long + Unknown error occurred From To Profile: %1$s diff --git a/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/DirectionsViewModelTest.kt b/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/DirectionsViewModelTest.kt index 912af31..4bb06eb 100644 --- a/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/DirectionsViewModelTest.kt +++ b/cardinal-android/app/src/test/java/earth/maps/cardinal/ui/directions/DirectionsViewModelTest.kt @@ -312,7 +312,8 @@ class DirectionsViewModelTest { advanceUntilIdle() assertFalse(state.isLoading) - assertTrue(state.routes.isEmpty()) + val updatedState = viewModel.routeState.value + assertTrue(updatedState.routes.isEmpty()) coVerifyOrder { mockRouteStateRepository.setLoading(true) mockRouteStateRepository.setDirectionError(DirectionUiError.DistanceExceeded) -- GitLab From c3b9106b46b9db122d14673343e9cf68035169e8 Mon Sep 17 00:00:00 2001 From: mitulsheth Date: Wed, 18 Mar 2026 15:40:46 +0530 Subject: [PATCH 4/4] fix(code-review): This itinerary is too long - Resolved code review messages --- .../maps/cardinal/data/RouteStateRepository.kt | 4 ++-- .../cardinal/ui/directions/DirectionUiError.kt | 18 ++++++++++++++++++ .../cardinal/ui/directions/DirectionsScreen.kt | 2 +- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt index 5626ae2..8031761 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/data/RouteStateRepository.kt @@ -53,8 +53,8 @@ class RouteStateRepository { _routeState.value = _routeState.value.copy(isLoading = false, error = error) } - fun setDirectionError(directionError: DirectionUiError?) { - _routeState.value = _routeState.value.copy(isLoading = false, directionError = directionError, error = null) + fun setDirectionError(directionUiError: DirectionUiError?) { + _routeState.value = _routeState.value.copy(isLoading = false, directionError = directionUiError, error = null) } fun clear() { diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt index d8364d9..bbe0c62 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionUiError.kt @@ -1,4 +1,22 @@ +/* + * Cardinal Maps + * Copyright (C) 2025 Cardinal Maps Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package earth.maps.cardinal.ui.directions + import uniffi.ferrostar.ParsingException sealed class DirectionUiError { diff --git a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt index 099d416..19d8664 100644 --- a/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt +++ b/cardinal-android/app/src/main/java/earth/maps/cardinal/ui/directions/DirectionsScreen.kt @@ -500,7 +500,7 @@ private fun NonTransitRouteResults( val message = when (routeState.directionError) { DirectionUiError.DistanceExceeded -> stringResource(string.long_itinerary_error_message) is DirectionUiError.Unknown -> routeState.directionError.message?.let { - stringResource(string.directions_error, routeState.directionError.message) + stringResource(string.directions_error, it) } ?: stringResource(string.unknown_error) } Text( -- GitLab