diff --git a/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/nearbyTransit/NearbyTransitViewTest.kt b/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/nearbyTransit/NearbyTransitViewTest.kt index e8444534b..d2317683e 100644 --- a/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/nearbyTransit/NearbyTransitViewTest.kt +++ b/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/nearbyTransit/NearbyTransitViewTest.kt @@ -1,5 +1,6 @@ package com.mbta.tid.mbta_app.android.nearbyTransit +import androidx.compose.material3.Text import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.hasText @@ -22,6 +23,8 @@ import com.mbta.tid.mbta_app.repositories.IPinnedRoutesRepository import com.mbta.tid.mbta_app.repositories.IPredictionsRepository import com.mbta.tid.mbta_app.repositories.IRailRouteShapeRepository import com.mbta.tid.mbta_app.repositories.ISchedulesRepository +import com.mbta.tid.mbta_app.repositories.MockNearbyRepository +import com.mbta.tid.mbta_app.repositories.MockPredictionsRepository import com.mbta.tid.mbta_app.repositories.MockRailRouteShapeRepository import com.mbta.tid.mbta_app.repositories.MockScheduleRepository import com.mbta.tid.mbta_app.usecases.TogglePinnedRouteUsecase @@ -242,7 +245,8 @@ class NearbyTransitViewTest : KoinTest { targetLocation = Position(0.0, 0.0), setLastLocation = {}, setSelectingLocation = {}, - onOpenStopDetails = { _, _ -> } + onOpenStopDetails = { _, _ -> }, + noNearbyStopsView = {} ) } } @@ -258,4 +262,50 @@ class NearbyTransitViewTest : KoinTest { composeTestRule.onNodeWithText("Green Line Head Sign").assertIsDisplayed() composeTestRule.onNodeWithText("5 min").assertIsDisplayed() } + + @OptIn(ExperimentalTestApi::class) + @Test + fun testNearbyTransitViewNoNearbyStops() { + val emptyNearbyKoinApplication = koinApplication { + modules( + module { + single { MockNearbyRepository() } + single { MockScheduleRepository() } + single { + MockPredictionsRepository( + connectV2Response = + PredictionsByStopJoinResponse(emptyMap(), emptyMap(), emptyMap()) + ) + } + single { + object : IPinnedRoutesRepository { + override suspend fun getPinnedRoutes(): Set { + return emptySet() + } + + override suspend fun setPinnedRoutes(routes: Set) {} + } + } + single { TogglePinnedRouteUsecase(get()) } + } + ) + } + composeTestRule.setContent { + KoinContext(emptyNearbyKoinApplication.koin) { + NearbyTransitView( + alertData = AlertsStreamDataResponse(emptyMap()), + globalResponse = globalResponse, + targetLocation = Position(0.0, 0.0), + setLastLocation = {}, + setSelectingLocation = {}, + onOpenStopDetails = { _, _ -> }, + noNearbyStopsView = { Text("This would be the no nearby stops view") } + ) + } + } + + composeTestRule.waitForIdle() + composeTestRule.waitUntilExactlyOneExists(hasText("This would be the no nearby stops view")) + composeTestRule.onNodeWithText("This would be the no nearby stops view").assertIsDisplayed() + } } diff --git a/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/nearbyTransit/NoNearbyStopsViewTest.kt b/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/nearbyTransit/NoNearbyStopsViewTest.kt new file mode 100644 index 000000000..dc1ea23c8 --- /dev/null +++ b/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/nearbyTransit/NoNearbyStopsViewTest.kt @@ -0,0 +1,40 @@ +package com.mbta.tid.mbta_app.android.nearbyTransit + +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import kotlin.test.assertTrue +import org.junit.Rule +import org.junit.Test + +class NoNearbyStopsViewTest { + @get:Rule val composeTestRule = createComposeRule() + + @Test + fun displaysText() { + composeTestRule.setContent { NoNearbyStopsView({}, {}) } + + composeTestRule.onNodeWithText("No nearby stops").assertIsDisplayed() + composeTestRule.onNodeWithText("You’re outside the MBTA service area.").assertIsDisplayed() + composeTestRule.onNodeWithText("Search by stop").assertIsDisplayed() + composeTestRule.onNodeWithText("View transit near Boston").assertIsDisplayed() + } + + @Test + fun buttonsWork() { + var openedSearch = false + var pannedToDefaultCenter = false + composeTestRule.setContent { + NoNearbyStopsView( + onOpenSearch = { openedSearch = true }, + onPanToDefaultCenter = { pannedToDefaultCenter = true } + ) + } + + composeTestRule.onNodeWithText("Search by stop").performClick() + assertTrue(openedSearch) + composeTestRule.onNodeWithText("View transit near Boston").performClick() + assertTrue(pannedToDefaultCenter) + } +} diff --git a/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/state/GetScheduleTest.kt b/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/state/GetScheduleTest.kt index aaa848c6e..920265462 100644 --- a/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/state/GetScheduleTest.kt +++ b/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/state/GetScheduleTest.kt @@ -8,6 +8,8 @@ import com.mbta.tid.mbta_app.model.ObjectCollectionBuilder import com.mbta.tid.mbta_app.model.response.ApiResult import com.mbta.tid.mbta_app.model.response.ScheduleResponse import com.mbta.tid.mbta_app.repositories.ISchedulesRepository +import com.mbta.tid.mbta_app.repositories.MockScheduleRepository +import kotlin.test.assertNotNull import kotlinx.coroutines.test.runTest import kotlinx.datetime.Instant import org.junit.Assert.assertEquals @@ -61,4 +63,20 @@ class GetScheduleTest { composeTestRule.awaitIdle() assertEquals(expectedSchedules2, actualSchedules) } + + @Test + fun testScheduleNoStops() { + val schedulesRepo = + MockScheduleRepository( + callback = { stopIds -> assertEquals(emptyList(), stopIds) } + ) + var actualSchedules: ScheduleResponse? = null + + composeTestRule.setContent { + actualSchedules = getSchedule(stopIds = emptyList(), schedulesRepo) + } + + composeTestRule.waitUntil { actualSchedules != null } + assertNotNull(actualSchedules) + } } diff --git a/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/state/SubscribeToPredictionsTest.kt b/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/state/SubscribeToPredictionsTest.kt index 160df2c0a..f7be6f1e3 100644 --- a/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/state/SubscribeToPredictionsTest.kt +++ b/androidApp/src/androidTest/java/com/mbta/tid/mbta_app/android/state/SubscribeToPredictionsTest.kt @@ -14,6 +14,8 @@ import com.mbta.tid.mbta_app.model.ObjectCollectionBuilder import com.mbta.tid.mbta_app.model.response.PredictionsByStopJoinResponse import com.mbta.tid.mbta_app.model.response.PredictionsStreamDataResponse import com.mbta.tid.mbta_app.repositories.MockPredictionsRepository +import kotlin.test.assertNotNull +import kotlin.test.assertTrue import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Rule @@ -54,7 +56,7 @@ class SubscribeToPredictionsTest { composeTestRule.waitUntil { predictions != null && - predictions == predictionsOnJoin?.toPredictionsStreamDataResponse() + predictions == predictionsOnJoin.toPredictionsStreamDataResponse() } assertEquals(0, disconnectCount) @@ -105,4 +107,28 @@ class SubscribeToPredictionsTest { composeTestRule.waitUntil { connectCount == 2 } assertEquals(1, disconnectCount) } + + @Test + fun testEmptyStopList() { + var connected = false + val predictionsRepo = + MockPredictionsRepository( + onConnectV2 = { stopIds -> + assertEquals(emptyList(), stopIds) + connected = true + }, + connectV2Response = + PredictionsByStopJoinResponse(emptyMap(), emptyMap(), emptyMap()) + ) + + var predictions: PredictionsStreamDataResponse? = null + + composeTestRule.setContent { + predictions = subscribeToPredictions(emptyList(), predictionsRepo) + } + + composeTestRule.waitUntil { predictions != null } + assertNotNull(predictions) + assertTrue(connected) + } } diff --git a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/nearbyTransit/NearbyTransitView.kt b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/nearbyTransit/NearbyTransitView.kt index 1291cb044..dd50fc512 100644 --- a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/nearbyTransit/NearbyTransitView.kt +++ b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/nearbyTransit/NearbyTransitView.kt @@ -2,9 +2,12 @@ package com.mbta.tid.mbta_app.android.nearbyTransit import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -30,13 +33,13 @@ import kotlin.time.Duration.Companion.seconds @Composable fun NearbyTransitView( - modifier: Modifier = Modifier, alertData: AlertsStreamDataResponse?, globalResponse: GlobalResponse?, targetLocation: Position?, setLastLocation: (Position) -> Unit, setSelectingLocation: (Boolean) -> Unit, onOpenStopDetails: (String, StopDetailsFilter?) -> Unit, + noNearbyStopsView: @Composable () -> Unit, ) { var nearby: NearbyStaticData? = getNearby( @@ -79,7 +82,7 @@ fun NearbyTransitView( } } - Column(modifier) { + Column { Text( text = stringResource(R.string.nearby_transit), modifier = Modifier.padding(bottom = 12.dp, start = 16.dp, end = 16.dp), @@ -87,20 +90,17 @@ fun NearbyTransitView( ) if (nearbyWithRealtimeInfo == null) { - Text(text = stringResource(R.string.loading), modifier) + Text(text = stringResource(R.string.loading)) } else if (nearbyWithRealtimeInfo.isEmpty()) { - Column(Modifier.padding(8.dp).weight(1f), verticalArrangement = Arrangement.Center) { - Text( - stringResource(R.string.no_stops_nearby_title), - style = MaterialTheme.typography.titleMedium - ) - Text( - stringResource(R.string.no_stops_nearby), - style = MaterialTheme.typography.bodyMedium - ) + Column( + Modifier.verticalScroll(rememberScrollState()).padding(8.dp).weight(1f), + verticalArrangement = Arrangement.Center + ) { + noNearbyStopsView() + Spacer(Modifier.weight(1f)) } } else { - LazyColumn(modifier) { + LazyColumn { items(nearbyWithRealtimeInfo) { when (it) { is StopsAssociated.WithRoute -> diff --git a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/nearbyTransit/NoNearbyStopsView.kt b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/nearbyTransit/NoNearbyStopsView.kt new file mode 100644 index 000000000..7ccfc107f --- /dev/null +++ b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/nearbyTransit/NoNearbyStopsView.kt @@ -0,0 +1,107 @@ +package com.mbta.tid.mbta_app.android.nearbyTransit + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredHeightIn +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mbta.tid.mbta_app.android.MyApplicationTheme +import com.mbta.tid.mbta_app.android.R + +@Composable +fun NoNearbyStopsView(onOpenSearch: () -> Unit, onPanToDefaultCenter: () -> Unit) { + Column( + modifier = + Modifier.clip(RoundedCornerShape(8.dp)) + .background(colorResource(R.color.fill3)) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalAlignment = Alignment.Start + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painterResource(R.drawable.mbta_logo), + contentDescription = null, + modifier = Modifier.size(48.dp), + tint = Color.Unspecified + ) + Text( + stringResource(R.string.no_stops_nearby_title), + style = MaterialTheme.typography.titleLarge + ) + } + Text(stringResource(R.string.no_stops_nearby), style = MaterialTheme.typography.bodyMedium) + Button( + onClick = onOpenSearch, + modifier = Modifier.requiredHeightIn(min = 48.dp), + shape = RoundedCornerShape(8.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + stringResource(R.string.no_stops_nearby_search), + style = MaterialTheme.typography.bodyMedium + ) + Icon( + painterResource(R.drawable.fa_magnifying_glass_solid), + contentDescription = null, + modifier = Modifier.size(16.dp) + ) + } + } + OutlinedButton( + onClick = onPanToDefaultCenter, + modifier = Modifier.requiredHeightIn(min = 48.dp), + shape = RoundedCornerShape(8.dp), + border = BorderStroke(1.dp, colorResource(R.color.key)) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + stringResource(R.string.no_stops_nearby_pan), + style = MaterialTheme.typography.bodyMedium + ) + Icon( + painterResource(R.drawable.fa_map), + contentDescription = null, + modifier = Modifier.size(16.dp) + ) + } + } + } +} + +@Preview +@Composable +private fun NoNearbyStopsViewPreview() { + MyApplicationTheme { NoNearbyStopsView({}, {}) } +} diff --git a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/pages/NearbyTransitPage.kt b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/pages/NearbyTransitPage.kt index f20fa43ec..9a18de383 100644 --- a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/pages/NearbyTransitPage.kt +++ b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/pages/NearbyTransitPage.kt @@ -19,6 +19,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity @@ -40,6 +41,7 @@ import com.mbta.tid.mbta_app.android.map.IMapViewModel import com.mbta.tid.mbta_app.android.map.MapViewModel import com.mbta.tid.mbta_app.android.nearbyTransit.NearbyTransitTabViewModel import com.mbta.tid.mbta_app.android.nearbyTransit.NearbyTransitView +import com.mbta.tid.mbta_app.android.nearbyTransit.NoNearbyStopsView import com.mbta.tid.mbta_app.android.search.SearchBarOverlay import com.mbta.tid.mbta_app.android.state.subscribeToVehicles import com.mbta.tid.mbta_app.android.util.toPosition @@ -87,12 +89,25 @@ fun NearbyTransitPage( val stopDetailsFilter by viewModel.stopDetailsFilter.collectAsState() var vehiclesData: List = subscribeToVehicles(routeDirection = stopDetailsFilter) + val searchFocusRequester = remember { FocusRequester() } + fun handleStopNavigation(stopId: String) { navController.navigate(SheetRoutes.StopDetails(stopId, null, null)) { popUpTo(SheetRoutes.NearbyTransit) } } + fun openSearch() { + searchFocusRequester.requestFocus() + } + + fun panToDefaultCenter() { + nearbyTransit.viewportProvider.animateTo( + ViewportProvider.Companion.Defaults.center, + zoom = 13.75 + ) + } + fun updateStopFilter(filter: StopDetailsFilter?) { viewModel.setStopDetailsFilter(filter) } @@ -106,7 +121,7 @@ fun NearbyTransitPage( mapViewModel.setGlobalResponse(nearbyTransit.globalResponse) } - SearchBarOverlay(::handleStopNavigation, currentNavEntry) { + SearchBarOverlay(::handleStopNavigation, currentNavEntry, searchFocusRequester) { Scaffold(bottomBar = bottomBar) { outerSheetPadding -> BottomSheetScaffold( sheetDragHandle = { DragHandle() }, @@ -241,6 +256,9 @@ fun NearbyTransitPage( filter?.directionId ) ) + }, + noNearbyStopsView = { + NoNearbyStopsView(::openSearch, ::panToDefaultCenter) } ) } diff --git a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/search/SearchBarOverlay.kt b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/search/SearchBarOverlay.kt index 24ded1faa..72a91444f 100644 --- a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/search/SearchBarOverlay.kt +++ b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/search/SearchBarOverlay.kt @@ -25,6 +25,8 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -41,6 +43,7 @@ import com.mbta.tid.mbta_app.android.state.getSearchResultsVm fun SearchBarOverlay( onStopNavigation: (stopId: String) -> Unit, currentNavEntry: NavBackStackEntry?, + inputFieldFocusRequester: FocusRequester, content: @Composable () -> Unit ) { var visible = @@ -96,6 +99,7 @@ fun SearchBarOverlay( expanded = expanded, onQueryChange = { searchInputState = it }, onExpandedChange = { expanded = it }, + modifier = Modifier.focusRequester(inputFieldFocusRequester), onSearch = {}, leadingIcon = { Icon( diff --git a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/state/getSchedule.kt b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/state/getSchedule.kt index b66e72d00..20b9795d6 100644 --- a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/state/getSchedule.kt +++ b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/state/getSchedule.kt @@ -37,6 +37,8 @@ class ScheduleViewModel( /* TODO("handle errors") */ } } + } else { + _schedule.value = ScheduleResponse(emptyList(), emptyMap()) } } } diff --git a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/state/subscribeToPredictions.kt b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/state/subscribeToPredictions.kt index 5357576d9..4e36baf0f 100644 --- a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/state/subscribeToPredictions.kt +++ b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/state/subscribeToPredictions.kt @@ -37,8 +37,7 @@ class PredictionsViewModel( } fun connect(stopIds: List?) { - - if (!stopIds.isNullOrEmpty()) { + if (stopIds != null) { predictionsRepository.connectV2(stopIds, ::handleJoinMessage, ::handlePushMessage) } } diff --git a/androidApp/src/main/res/drawable/fa_magnifying_glass_solid.xml b/androidApp/src/main/res/drawable/fa_magnifying_glass_solid.xml new file mode 100644 index 000000000..1de67f628 --- /dev/null +++ b/androidApp/src/main/res/drawable/fa_magnifying_glass_solid.xml @@ -0,0 +1,9 @@ + + + diff --git a/androidApp/src/main/res/drawable/fa_map.xml b/androidApp/src/main/res/drawable/fa_map.xml new file mode 100644 index 000000000..cdbbb897a --- /dev/null +++ b/androidApp/src/main/res/drawable/fa_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/androidApp/src/main/res/values-b+es/strings_ios_converted.xml b/androidApp/src/main/res/values-b+es/strings_ios_converted.xml index 161c50dfa..2993a8430 100644 --- a/androidApp/src/main/res/values-b+es/strings_ios_converted.xml +++ b/androidApp/src/main/res/values-b+es/strings_ios_converted.xml @@ -31,6 +31,8 @@ Sin servicio No hay servicio hoy Estás fuera del área de servicio de MBTA. + Ver el tránsito cerca de Boston + Buscar por parada No hay paradas cercanas En dirección norte Ahora diff --git a/androidApp/src/main/res/values-b+ht/strings_ios_converted.xml b/androidApp/src/main/res/values-b+ht/strings_ios_converted.xml index 44aa204bc..c391616ce 100644 --- a/androidApp/src/main/res/values-b+ht/strings_ios_converted.xml +++ b/androidApp/src/main/res/values-b+ht/strings_ios_converted.xml @@ -31,6 +31,8 @@ Pa gen Sèvis Pa gen sèvis jodi a Ou andeyò zòn sèvis MBTA a. + Gade transpò piblik toupre Boston + Chèche pa kanpe Pa gen arè ki tou pre Nan direksyon nò Kounye a diff --git a/androidApp/src/main/res/values-b+pt+BR/strings_ios_converted.xml b/androidApp/src/main/res/values-b+pt+BR/strings_ios_converted.xml index 51c53f905..7ee64b257 100644 --- a/androidApp/src/main/res/values-b+pt+BR/strings_ios_converted.xml +++ b/androidApp/src/main/res/values-b+pt+BR/strings_ios_converted.xml @@ -31,6 +31,8 @@ Sem serviço Sem serviço hoje Você está fora da área de serviço da MBTA. + Ver trânsito perto de Boston + Pesquisar por parada Nenhuma parada próxima Sentido norte Agora diff --git a/androidApp/src/main/res/values-b+vi/strings_ios_converted.xml b/androidApp/src/main/res/values-b+vi/strings_ios_converted.xml index 2646d22fc..2827f9e60 100644 --- a/androidApp/src/main/res/values-b+vi/strings_ios_converted.xml +++ b/androidApp/src/main/res/values-b+vi/strings_ios_converted.xml @@ -31,6 +31,8 @@ Không có dịch vụ Hôm nay không có dịch vụ Bạn đang ở ngoài khu vực dịch vụ của MBTA. + Xem phương tiện giao thông gần Boston + Tìm kiếm theo điểm dừng Không có điểm dừng gần đó Về hướng bắc Hiện nay diff --git a/androidApp/src/main/res/values-b+zh+Hans+CN/strings_ios_converted.xml b/androidApp/src/main/res/values-b+zh+Hans+CN/strings_ios_converted.xml index 93592f61c..bf4d81243 100644 --- a/androidApp/src/main/res/values-b+zh+Hans+CN/strings_ios_converted.xml +++ b/androidApp/src/main/res/values-b+zh+Hans+CN/strings_ios_converted.xml @@ -31,6 +31,8 @@ 无服务 今日无服务 您位于 MBTA 服务区之外。 + 查看波士顿附近的交通 + 按站点搜索 附近无站点 北行 现在 diff --git a/androidApp/src/main/res/values-b+zh+Hant+TW/strings_ios_converted.xml b/androidApp/src/main/res/values-b+zh+Hant+TW/strings_ios_converted.xml index 5aeb2b605..9c72c63d8 100644 --- a/androidApp/src/main/res/values-b+zh+Hant+TW/strings_ios_converted.xml +++ b/androidApp/src/main/res/values-b+zh+Hant+TW/strings_ios_converted.xml @@ -31,6 +31,8 @@ 無服務 今日無服務 您位於 MBTA 服務區域之外。 + 查看波士頓附近的交通 + 按站點搜尋 附近沒有停靠站 北行 現在 diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml index 0858bd485..2e1263ef8 100644 --- a/androidApp/src/main/res/values/strings.xml +++ b/androidApp/src/main/res/values/strings.xml @@ -33,6 +33,8 @@ No Service No service today You’re outside the MBTA service area. + View transit near Boston + Search by stop No nearby stops Northbound Now