Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: show filtered departures in stop details #124

Merged
merged 8 commits into from
Apr 10, 2024

Conversation

boringcactus
Copy link
Member

@boringcactus boringcactus commented Apr 9, 2024

Summary

Ticket: Show detailed departures for a route + direction

Implements the full list of upcoming departures for a route and direction filter in the stop details page.

Stacked on #122.

Testing

Manually verified continuing functionality and added new unit tests.

@boringcactus boringcactus requested a review from a team as a code owner April 9, 2024 22:47
@boringcactus boringcactus requested review from KaylaBrady and removed request for a team April 9, 2024 22:47
Button(action: {
filter = .init(routeId: patternsByHeadsign.route.id, directionId: patternsByHeadsign.directionId())
}, label: {
NearbyStopRoutePatternView(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (non-blocking): Since this is no longer exclusive to the nearby view, it might be worth renaming this to something more general / descriptive, though that could be a separate follow-up.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember wanting to do that but not being able to think of a perfect component name. Since it's a single row designed to be contained in a trip card, and it may contain one trip or multiple trips but it will always have a headsign, it seems like HeadsignRowView is good enough of a name for it.

let tripsFormatted: [(PatternsByHeadsign, PatternsByHeadsign.Format)] = trips.map { ($0, $0.format(now: now)) }
tripData = tripsFormatted.filter {
let (patternsByHeadsign, formatted) = $0
let trip: UpcomingTrip? = patternsByHeadsign.upcomingTrips?.first
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Is splitPerTrip needed? I found it a bit confusing on initial read that trips is a list of PatternsByHeadsign rather than a list of trips, and that by using splitByTrip there is only ever 1 trip in the list of upcomingTrips.

Would it be viable to keep the list of UpcomingTrips grouped by headsign and do a nested ForEach over the list of patternsByHeadsign and the list of upcomingTrips for each headsign? That way when we see PatternsByHeadsign used we can assume it is representing the same data as when it is used in other cases - a list of all trips for a headsign.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A nested ForEach would not work, because we need the individual trips to be sorted by time even if that means interleaving the headsigns together. We need to be calling PatternsByHeadsign.format() because that's where the logic that hides subway schedules is (since the UpcomingTrip doesn't know its Route directly). However, if we want a more coherent abstraction boundary, we can change splitPerTrip(): List<PatternsByHeadsign> to allUpcomingTrips(): List<UpcomingTrip> and then reconstruct the PatternsByHeadsign as part of the presentation layer instead.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I hadn't considered the interleaving piece!

Comment on lines +38 to +39
_ = self.popLast()
self.append(.stopDetails(stop, newValue))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (non-blocking): Am I reading this correctly that there is only ever 1 item in the navigation stack?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code does not make that assumption, although since the only links in the app go from nearby transit to stop details, there is currently no way to have multiple entries in the navigation stack.

Comment on lines 20 to 21
let selectedData = departures.routes.first(where: { $0.route.id == filter.routeId })!
StopDetailsFilteredRouteView(patternsByStop: selectedData, now: now, filter: $filter)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (non-blocking): the departures are filtered by route here, but by direction within StopDetailsFilteredRouteView. I wonder if for consistency purposes it would make sense to filter by both route + direction either fully inside StopDetailsFilteredRouteView or fully outside of it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, yeah.

XCTAssertEqual(stack, [])
}

func testLastFilterShallow() throws {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick(non-blocking): I'm not picking up what is Shallow vs Deep between these two tests, maybe some additional description would help?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the navigation stack that's shallow when there's no previous history and deep when there's previous history. I've added more pages to the deep test to clarify what sets that test apart from the shallow test.

@@ -0,0 +1,75 @@
//
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: Great work unit testing these pieces!

Base automatically changed from mth-prepare-stop-details-filter to main April 10, 2024 16:26
@boringcactus boringcactus force-pushed the mth-stop-direction-filter branch from bf7fa6c to 66582bc Compare April 10, 2024 16:27
tripId = trip.trip.id
headsign = trip.trip.headsign
formatted = PatternsByHeadsign(
route: route, headsign: headsign, patterns: [], upcomingTrips: [trip], alertsHere: nil
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (non-blocking): does losing alertsHere data limit how what we can render in alerts scenarios?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because rendering the alert once for each upcoming trip would be incorrect; it looks like the spec for handling alerts in stop details hasn't been written yet, but whatever we settle on will be outside of the individual trips.

let tripsFormatted: [(PatternsByHeadsign, PatternsByHeadsign.Format)] = trips.map { ($0, $0.format(now: now)) }
tripData = tripsFormatted.filter {
let (patternsByHeadsign, formatted) = $0
let trip: UpcomingTrip? = patternsByHeadsign.upcomingTrips?.first
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I hadn't considered the interleaving piece!

Copy link
Collaborator

@KaylaBrady KaylaBrady left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Thanks for doing the renaming.

@boringcactus boringcactus merged commit f7ab56e into main Apr 10, 2024
5 checks passed
@boringcactus boringcactus deleted the mth-stop-direction-filter branch April 10, 2024 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants