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 03495d51e..d1020bb63 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 @@ -2,6 +2,7 @@ package com.mbta.tid.mbta_app.android.state import androidx.activity.ComponentActivity import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -52,7 +53,7 @@ class SubscribeToPredictionsTest { composeTestRule.setContent { var stopIds by remember { stopIds } - predictions = + val predictionsVM = subscribeToPredictions( stopIds, predictionsRepo, @@ -62,6 +63,7 @@ class SubscribeToPredictionsTest { MockSettingsRepository() ) ) + predictions = predictionsVM.predictionsFlow.collectAsState(initial = null).value } composeTestRule.waitUntil { connectProps == listOf("place-a") } @@ -102,7 +104,7 @@ class SubscribeToPredictionsTest { composeTestRule.setContent { CompositionLocalProvider(LocalLifecycleOwner provides lifecycleOwner) { var stopIds by remember { stopIds } - predictions = + val predictionsVM = subscribeToPredictions( stopIds, predictionsRepo, @@ -112,6 +114,7 @@ class SubscribeToPredictionsTest { MockSettingsRepository() ) ) + predictions = predictionsVM.predictionsFlow.collectAsState(initial = null).value } } @@ -145,7 +148,7 @@ class SubscribeToPredictionsTest { var predictions: PredictionsStreamDataResponse? = null composeTestRule.setContent { - predictions = + val predictionsVM = subscribeToPredictions( emptyList(), predictionsRepo, @@ -155,6 +158,7 @@ class SubscribeToPredictionsTest { MockSettingsRepository() ) ) + predictions = predictionsVM.predictionsFlow.collectAsState(initial = null).value } composeTestRule.waitUntil { predictions != null } 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 bdafb2b95..e3faa284b 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 @@ -13,6 +13,8 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -65,7 +67,13 @@ fun NearbyTransitView( val now = timer(updateInterval = 5.seconds) val stopIds = remember(nearbyVM.nearby) { nearbyVM.nearby?.stopIds()?.toList() } val schedules = getSchedule(stopIds) - val predictions = subscribeToPredictions(stopIds, errorBannerViewModel = errorBannerViewModel) + val predictionsVM = subscribeToPredictions(stopIds, errorBannerViewModel = errorBannerViewModel) + val predictions by predictionsVM.predictionsFlow.collectAsState(initial = null) + LaunchedEffect(targetLocation == null) { + if (targetLocation == null) { + predictionsVM.reset() + } + } val (pinnedRoutes, togglePinnedRoute) = managePinnedRoutes() 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 7717a5fe0..600683fc0 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 @@ -46,6 +46,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.NearbyTransitViewModel 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 @@ -64,6 +65,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.launch +import org.koin.androidx.compose.koinViewModel import org.koin.compose.koinInject @OptIn(ExperimentalMaterial3Api::class) @@ -216,6 +218,8 @@ fun NearbyTransitPage( } } composable { + // for ViewModel reasons, must be within the `composable` to be the same instance + val nearbyViewModel: NearbyTransitViewModel = koinViewModel() LaunchedEffect(true) { if (!navBarVisible) { showNavBar() @@ -234,13 +238,13 @@ fun NearbyTransitPage( } LaunchedEffect(nearbyTransit.viewportProvider.isManuallyCentering) { if (nearbyTransit.viewportProvider.isManuallyCentering) { - // TODO reset view model + nearbyViewModel.reset() targetLocation = null } } LaunchedEffect(nearbyTransit.viewportProvider.isFollowingPuck) { if (nearbyTransit.viewportProvider.isFollowingPuck) { - // TODO reset view model + nearbyViewModel.reset() targetLocation = null } } diff --git a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/pages/StopDetailsPage.kt b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/pages/StopDetailsPage.kt index 449888e40..f52cf5a06 100644 --- a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/pages/StopDetailsPage.kt +++ b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/pages/StopDetailsPage.kt @@ -3,6 +3,8 @@ package com.mbta.tid.mbta_app.android.pages import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import com.mapbox.maps.MapboxExperimental import com.mbta.tid.mbta_app.android.component.ErrorBannerViewModel @@ -36,11 +38,12 @@ fun StopDetailsPage( ) { val globalResponse = getGlobalData() - val predictionsResponse = + val predictionsVM = subscribeToPredictions( stopIds = listOf(stop.id), errorBannerViewModel = errorBannerViewModel ) + val predictionsResponse by predictionsVM.predictionsFlow.collectAsState(initial = null) val now = timer(updateInterval = 5.seconds) diff --git a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/phoenix/PhoenixSocketWrapper.kt b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/phoenix/PhoenixSocketWrapper.kt index c4a1411b9..4a8c9ae88 100644 --- a/androidApp/src/main/java/com/mbta/tid/mbta_app/android/phoenix/PhoenixSocketWrapper.kt +++ b/androidApp/src/main/java/com/mbta/tid/mbta_app/android/phoenix/PhoenixSocketWrapper.kt @@ -20,7 +20,9 @@ value class PhoenixSocketWrapper(private val socket: Socket) : PhoenixSocket { fun attachLogging() { socket.onMessage { message -> Log.i("Socket", message.toString()) } - socket.onError { throwable, response -> Log.e("Socket", response.toString(), throwable) } + socket.onError { throwable, response -> + Log.e("Socket", response?.toString() ?: throwable.toString(), throwable) + } } } 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 137513542..48c1eb40b 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 @@ -2,7 +2,6 @@ package com.mbta.tid.mbta_app.android.state import android.util.Log import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.compose.LifecycleResumeEffect @@ -11,7 +10,6 @@ import com.mbta.tid.mbta_app.android.component.ErrorBannerViewModel import com.mbta.tid.mbta_app.model.response.ApiResult import com.mbta.tid.mbta_app.model.response.PredictionsByStopJoinResponse import com.mbta.tid.mbta_app.model.response.PredictionsByStopMessageResponse -import com.mbta.tid.mbta_app.model.response.PredictionsStreamDataResponse import com.mbta.tid.mbta_app.repositories.IPredictionsRepository import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineScope @@ -86,6 +84,10 @@ class PredictionsViewModel( } } + fun reset() { + _predictions.value = null + } + fun disconnect() { predictionsRepository.disconnect() errorBannerViewModel.loadingWhenPredictionsStale = true @@ -119,7 +121,7 @@ fun subscribeToPredictions( stopIds: List?, predictionsRepository: IPredictionsRepository = koinInject(), errorBannerViewModel: ErrorBannerViewModel -): PredictionsStreamDataResponse? { +): PredictionsViewModel { val viewModel: PredictionsViewModel = viewModel( factory = PredictionsViewModel.Factory(predictionsRepository, errorBannerViewModel) @@ -133,5 +135,5 @@ fun subscribeToPredictions( onPauseOrDispose { viewModel.disconnect() } } - return viewModel.predictionsFlow.collectAsState(initial = null).value + return viewModel }