Skip to content

Commit dbdc34c

Browse files
authored
Merge pull request #154 from ellenhp/ellenhp/explicit_gtfs_ids
Pass explicit GTFS IDs around to ensure correct departures shown
2 parents 3a34432 + 02c64b2 commit dbdc34c

File tree

7 files changed

+35
-56
lines changed

7 files changed

+35
-56
lines changed

cardinal-android/app/src/main/java/earth/maps/cardinal/data/Place.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ data class Place(
2525
val address: Address? = null,
2626
val isMyLocation: Boolean = false,
2727
val isTransitStop: Boolean = false,
28+
val transitStopId: String? = null,
2829
)
2930

cardinal-android/app/src/main/java/earth/maps/cardinal/data/room/AppDatabase.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import earth.maps.cardinal.data.DownloadStatusConverter
2727

2828
@Database(
2929
entities = [OfflineArea::class, RoutingProfile::class, DownloadedTile::class, SavedList::class, SavedPlace::class, ListItem::class],
30-
version = 9,
30+
version = 10,
3131
exportSchema = false
3232
)
3333
@TypeConverters(TileTypeConverter::class, DownloadStatusConverter::class, ItemTypeConverter::class)
@@ -180,6 +180,14 @@ abstract class AppDatabase : RoomDatabase() {
180180
}
181181
}
182182

183+
private val MIGRATION_9_10 = object : Migration(9, 10) {
184+
override fun migrate(db: SupportSQLiteDatabase) {
185+
db.execSQL(
186+
"ALTER TABLE saved_places ADD COLUMN transitStopId TEXT"
187+
)
188+
}
189+
}
190+
183191

184192
fun getDatabase(context: Context): AppDatabase {
185193
return INSTANCE ?: synchronized(this) {
@@ -193,6 +201,7 @@ abstract class AppDatabase : RoomDatabase() {
193201
MIGRATION_6_7,
194202
MIGRATION_7_8,
195203
MIGRATION_8_9,
204+
MIGRATION_9_10,
196205
).build()
197206
INSTANCE = instance
198207
instance

cardinal-android/app/src/main/java/earth/maps/cardinal/data/room/SavedPlace.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ data class SavedPlace(
4242
val country: String? = null,
4343
val countryCode: String? = null,
4444
val isTransitStop: Boolean = false,
45+
val transitStopId: String? = null,
4546
val createdAt: Long,
4647
val updatedAt: Long
4748
) {
@@ -68,8 +69,9 @@ data class SavedPlace(
6869
country = place.address?.country,
6970
countryCode = place.address?.countryCode,
7071
isTransitStop = place.isTransitStop,
72+
transitStopId = place.transitStopId,
7173
createdAt = timestamp,
72-
updatedAt = timestamp
74+
updatedAt = timestamp,
7375
)
7476
}
7577
}

cardinal-android/app/src/main/java/earth/maps/cardinal/data/room/SavedPlaceRepository.kt

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,11 @@ class SavedPlaceRepository @Inject constructor(
4747
* Saves a place.
4848
*/
4949
suspend fun savePlace(
50-
place: Place,
51-
customName: String? = null,
52-
customDescription: String? = null
50+
place: Place, customName: String? = null, customDescription: String? = null
5351
): Result<String> = withContext(Dispatchers.IO) {
5452
try {
5553
val savedPlace = SavedPlace.fromPlace(place).copy(
56-
customName = customName,
57-
customDescription = customDescription
54+
customName = customName, customDescription = customDescription
5855
)
5956

6057
placeDao.insertPlace(savedPlace)
@@ -68,13 +65,12 @@ class SavedPlaceRepository @Inject constructor(
6865
* Updates a saved place.
6966
*/
7067
suspend fun updatePlace(
71-
placeId: String,
72-
customName: String? = null,
73-
customDescription: String? = null
68+
placeId: String, customName: String? = null, customDescription: String? = null
7469
): Result<Unit> = withContext(Dispatchers.IO) {
7570
try {
76-
val existingPlace = placeDao.getPlace(placeId)
77-
?: return@withContext Result.failure(IllegalArgumentException("Place not found"))
71+
val existingPlace = placeDao.getPlace(placeId) ?: return@withContext Result.failure(
72+
IllegalArgumentException("Place not found")
73+
)
7874

7975
val updatedPlace = existingPlace.copy(
8076
customName = customName ?: existingPlace.customName,
@@ -94,8 +90,9 @@ class SavedPlaceRepository @Inject constructor(
9490
*/
9591
suspend fun deletePlace(placeId: String): Result<Unit> = withContext(Dispatchers.IO) {
9692
try {
97-
val place = placeDao.getPlace(placeId)
98-
?: return@withContext Result.failure(IllegalArgumentException("Place not found"))
93+
val place = placeDao.getPlace(placeId) ?: return@withContext Result.failure(
94+
IllegalArgumentException("Place not found")
95+
)
9996

10097
placeDao.deletePlace(place)
10198
Result.success(Unit)
@@ -133,13 +130,9 @@ class SavedPlaceRepository @Inject constructor(
133130
description = savedPlace.type,
134131
icon = savedPlace.icon,
135132
latLng = earth.maps.cardinal.data.LatLng(
136-
latitude = savedPlace.latitude,
137-
longitude = savedPlace.longitude
133+
latitude = savedPlace.latitude, longitude = savedPlace.longitude
138134
),
139-
address = if (savedPlace.houseNumber != null || savedPlace.road != null || savedPlace.city != null ||
140-
savedPlace.state != null || savedPlace.postcode != null || savedPlace.country != null ||
141-
savedPlace.countryCode != null
142-
) {
135+
address = if (savedPlace.houseNumber != null || savedPlace.road != null || savedPlace.city != null || savedPlace.state != null || savedPlace.postcode != null || savedPlace.country != null || savedPlace.countryCode != null) {
143136
earth.maps.cardinal.data.Address(
144137
houseNumber = savedPlace.houseNumber,
145138
road = savedPlace.road,
@@ -152,7 +145,8 @@ class SavedPlaceRepository @Inject constructor(
152145
} else {
153146
null
154147
},
155-
isTransitStop = savedPlace.isTransitStop
148+
isTransitStop = savedPlace.isTransitStop,
149+
transitStopId = savedPlace.transitStopId,
156150
)
157151
}
158152
}

cardinal-android/app/src/main/java/earth/maps/cardinal/ui/TransitScreen.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,9 @@ fun TransitScreenContent(
147147
modifier = Modifier.padding(vertical = 8.dp)
148148
)
149149
} else {
150-
val maxDeparturesPerHeadsign = 3
151150
// List of departures grouped by route and headsign
152151
TransitScreenRouteDepartures(
153152
stopTimes = viewModel.departures.value,
154-
maxDepartures = maxDeparturesPerHeadsign,
155153
onRouteClicked = onRouteClicked,
156154
)
157155
}
@@ -162,7 +160,7 @@ fun TransitScreenContent(
162160
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class, ExperimentalTime::class)
163161
@Composable
164162
fun TransitScreenRouteDepartures(
165-
stopTimes: List<StopTime>, maxDepartures: Int, onRouteClicked: (Place) -> Unit
163+
stopTimes: List<StopTime>, onRouteClicked: (Place) -> Unit
166164
) {
167165
// Group departures by route name
168166
val departuresByRoute = stopTimes.groupBy { it.routeShortName }
@@ -182,7 +180,7 @@ fun TransitScreenRouteDepartures(
182180

183181
// Group departures by headsign within each route
184182
val departuresByHeadsign = departures.groupBy { it.headsign }.map { (key, value) ->
185-
(key to value.take(maxDepartures))
183+
(key to value.take(1))
186184
}.toMap()
187185
val headsigns = departuresByHeadsign.keys.toList().sorted()
188186

@@ -194,7 +192,8 @@ fun TransitScreenRouteDepartures(
194192
name = departure.place.name,
195193
description = transitStopString,
196194
latLng = LatLng(departure.place.lat, departure.place.lon),
197-
isTransitStop = true
195+
isTransitStop = true,
196+
transitStopId = departure.place.stopId,
198197
)
199198
}
200199
}.toMap()

cardinal-android/app/src/main/java/earth/maps/cardinal/ui/TransitStopScreen.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ fun TransitStopInformation(viewModel: TransitStopCardViewModel, onRouteClicked:
161161
modifier = Modifier.padding(vertical = 8.dp)
162162
)
163163
} else {
164-
val maxDeparturesPerHeadsign = 3
164+
val maxDeparturesPerHeadsign = 5
165165
// List of departures grouped by route and headsign
166166
RouteDepartures(
167167
stopTimes = viewModel.departures.value,

cardinal-android/app/src/main/java/earth/maps/cardinal/viewmodel/TransitStopCardViewModel.kt

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
2424
import earth.maps.cardinal.data.Place
2525
import earth.maps.cardinal.data.room.SavedPlaceDao
2626
import earth.maps.cardinal.transit.StopTime
27-
import earth.maps.cardinal.transit.TransitStop
2827
import earth.maps.cardinal.transit.TransitousService
2928
import kotlinx.coroutines.Job
3029
import kotlinx.coroutines.delay
@@ -44,7 +43,6 @@ class TransitStopCardViewModel @Inject constructor(
4443

4544
val isPlaceSaved = mutableStateOf(false)
4645
val stop = mutableStateOf<Place?>(null)
47-
val reverseGeocodedStop = mutableStateOf<TransitStop?>(null)
4846
val departures = mutableStateOf<List<StopTime>>(emptyList())
4947

5048
private val _didLoadingFail = MutableStateFlow(false)
@@ -85,7 +83,6 @@ class TransitStopCardViewModel @Inject constructor(
8583
val place = stop.value
8684
if (place != null) {
8785
checkIfPlaceIsSaved(place)
88-
reverseGeocodeStop(place)
8986
fetchDepartures()
9087
} else {
9188
Log.e(TAG, "Can't find departures for a `null` stop.")
@@ -102,34 +99,11 @@ class TransitStopCardViewModel @Inject constructor(
10299
}
103100
}
104101

105-
private suspend fun reverseGeocodeStop(place: Place) {
106-
_isLoading.value = true
107-
try {
108-
transitousService.reverseGeocode(
109-
name = place.name,
110-
latitude = place.latLng.latitude,
111-
longitude = place.latLng.longitude,
112-
type = "STOP"
113-
).collectLatest { stops ->
114-
reverseGeocodedStop.value = stops.firstOrNull()
115-
Log.d(TAG, "$reverseGeocodedStop")
116-
// Update the place with the reverse-geocoded name if available
117-
reverseGeocodedStop.value?.let { stop ->
118-
this@TransitStopCardViewModel.stop.value = place.copy(
119-
name = stop.name
120-
)
121-
}
122-
}
123-
} catch (e: Exception) {
124-
Log.e(TAG, "Failed to reverse geocode stop $place", e)
125-
}
126-
}
127-
128102
private suspend fun fetchDepartures() {
103+
_isLoading.value = true
129104
_isRefreshingDepartures.value = true
130105
try {
131-
// We need to get the stop ID from the reverse geocoded result
132-
reverseGeocodedStop.value?.id?.let { stopId ->
106+
stop.value?.transitStopId?.let { stopId ->
133107
if (stopId.isNotEmpty()) {
134108
transitousService.getStopTimes(stopId).collectLatest { response ->
135109
departures.value = response.stopTimes
@@ -138,7 +112,7 @@ class TransitStopCardViewModel @Inject constructor(
138112
}
139113
_didLoadingFail.value = false
140114
} catch (e: Exception) {
141-
Log.e(TAG, "Failed to fetch departures for $reverseGeocodedStop", e)
115+
Log.e(TAG, "Failed to fetch departures for $stop", e)
142116
_didLoadingFail.value = true
143117
} finally {
144118
_isRefreshingDepartures.value = false

0 commit comments

Comments
 (0)