Skip to content

Commit

Permalink
Merge branch 'main' into es-map-stop-tap
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmaSimon committed Apr 5, 2024
2 parents 43d96dd + 96e5ae5 commit 5b35d66
Show file tree
Hide file tree
Showing 16 changed files with 468 additions and 61 deletions.
16 changes: 16 additions & 0 deletions iosApp/iosApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
8C84D33E2B5AEE0200192C0A /* NearbyTransitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C84D33D2B5AEE0200192C0A /* NearbyTransitView.swift */; };
8CC1BB402B59D1F6005386FE /* LocationDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC1BB3F2B59D1F6005386FE /* LocationDataManager.swift */; };
8CD1F8CD2B7164C100F419D4 /* PredictionsFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1F8CC2B7164C100F419D4 /* PredictionsFetcher.swift */; };
8CE0140E2BBDB7C300918FAE /* RoutePillSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE0140D2BBDB7C300918FAE /* RoutePillSection.swift */; };
8CE014102BBDB8DC00918FAE /* StopDetailsRoutesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE0140F2BBDB8DC00918FAE /* StopDetailsRoutesView.swift */; };
8CE014122BBDB96900918FAE /* StopDetailsRouteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE014112BBDB96900918FAE /* StopDetailsRouteView.swift */; };
8CE014142BBDBE5200918FAE /* BackendProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE014132BBDBE5200918FAE /* BackendProvider.swift */; };
8CE0141B2BBF059B00918FAE /* SheetNavigationStackEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE0141A2BBF059A00918FAE /* SheetNavigationStackEntry.swift */; };
8CEA10232BA0F3C6001C6EB9 /* ScheduleFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CEA10222BA0F3C6001C6EB9 /* ScheduleFetcher.swift */; };
8CEA10252BA4B179001C6EB9 /* AlertsFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CEA10242BA4B179001C6EB9 /* AlertsFetcher.swift */; };
Expand Down Expand Up @@ -159,6 +163,10 @@
8C84D33D2B5AEE0200192C0A /* NearbyTransitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearbyTransitView.swift; sourceTree = "<group>"; };
8CC1BB3F2B59D1F6005386FE /* LocationDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationDataManager.swift; sourceTree = "<group>"; };
8CD1F8CC2B7164C100F419D4 /* PredictionsFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PredictionsFetcher.swift; sourceTree = "<group>"; };
8CE0140D2BBDB7C300918FAE /* RoutePillSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoutePillSection.swift; sourceTree = "<group>"; };
8CE0140F2BBDB8DC00918FAE /* StopDetailsRoutesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StopDetailsRoutesView.swift; sourceTree = "<group>"; };
8CE014112BBDB96900918FAE /* StopDetailsRouteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StopDetailsRouteView.swift; sourceTree = "<group>"; };
8CE014132BBDBE5200918FAE /* BackendProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackendProvider.swift; sourceTree = "<group>"; };
8CE0141A2BBF059A00918FAE /* SheetNavigationStackEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetNavigationStackEntry.swift; sourceTree = "<group>"; };
8CEA10222BA0F3C6001C6EB9 /* ScheduleFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleFetcher.swift; sourceTree = "<group>"; };
8CEA10242BA4B179001C6EB9 /* AlertsFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertsFetcher.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -399,6 +407,8 @@
isa = PBXGroup;
children = (
8C5054572BB5EB6C00C6A51C /* StopDetailsPage.swift */,
8CE0140F2BBDB8DC00918FAE /* StopDetailsRoutesView.swift */,
8CE014112BBDB96900918FAE /* StopDetailsRouteView.swift */,
);
path = StopDetails;
sourceTree = "<group>";
Expand Down Expand Up @@ -456,6 +466,7 @@
children = (
9A4E8E582B7EC4B90066B936 /* RoutePill.swift */,
9AB44A102B8FC43E00E8FFB3 /* IconCard.swift */,
8CE0140D2BBDB7C300918FAE /* RoutePillSection.swift */,
);
path = ComponentViews;
sourceTree = "<group>";
Expand Down Expand Up @@ -493,6 +504,7 @@
8CEA10222BA0F3C6001C6EB9 /* ScheduleFetcher.swift */,
8CEA10242BA4B179001C6EB9 /* AlertsFetcher.swift */,
9A5830572BA4A1A30039876E /* ViewportProvider.swift */,
8CE014132BBDBE5200918FAE /* BackendProvider.swift */,
);
path = Fetchers;
sourceTree = "<group>";
Expand Down Expand Up @@ -854,6 +866,7 @@
6EE7457E2B965ADE0052227E /* Socket.swift in Sources */,
9A5B27582BB22BF9009A6FC6 /* MapLayerManager.swift in Sources */,
9A03F3662BA9E68500DA40DC /* Debouncer.swift in Sources */,
8CE014102BBDB8DC00918FAE /* StopDetailsRoutesView.swift in Sources */,
9A8B34AD2B88E5090018412C /* RailRouteShapeFetcher.swift in Sources */,
9AB446B02BBDDCAF00D8C920 /* StopIcons.swift in Sources */,
9A2005CB2B97B68700F562E1 /* UpcomingTripView.swift in Sources */,
Expand All @@ -862,6 +875,7 @@
9A9E05F62B6D6EF70086B437 /* NearbyFetcher.swift in Sources */,
9A2005C92B97B65900F562E1 /* NearbyStopRoutePatternView.swift in Sources */,
9A4E8E592B7EC4B90066B936 /* RoutePill.swift in Sources */,
8CE014142BBDBE5200918FAE /* BackendProvider.swift in Sources */,
9A5B27562BB221C1009A6FC6 /* RouteLayerGenerator.swift in Sources */,
8CE0141B2BBF059B00918FAE /* SheetNavigationStackEntry.swift in Sources */,
8C5054582BB5EB6C00C6A51C /* StopDetailsPage.swift in Sources */,
Expand All @@ -873,6 +887,7 @@
9A887D572B683103006F5B80 /* SearchResultView.swift in Sources */,
8CEA10252BA4B179001C6EB9 /* AlertsFetcher.swift in Sources */,
9A5B275A2BB22D91009A6FC6 /* StopLayerGenerator.swift in Sources */,
8CE014122BBDB96900918FAE /* StopDetailsRouteView.swift in Sources */,
6E35D4D02B72C7B700A2BF95 /* HomeMapView.swift in Sources */,
8CC1BB402B59D1F6005386FE /* LocationDataManager.swift in Sources */,
ED3581662BB4706F005DDC34 /* PartialSheetModifier.swift in Sources */,
Expand All @@ -887,6 +902,7 @@
8C84D33E2B5AEE0200192C0A /* NearbyTransitView.swift in Sources */,
9AC10BDA2B80067400EA4605 /* ColorHexExtension.swift in Sources */,
9A37F3052BACCC40001714FE /* DoubleRoundedExtension.swift in Sources */,
8CE0140E2BBDB7C300918FAE /* RoutePillSection.swift in Sources */,
9A2005C52B97B5EA00F562E1 /* NearbyRouteView.swift in Sources */,
9A5830562BA3A2CE0039876E /* ViewportExtension.swift in Sources */,
9A5830582BA4A1A30039876E /* ViewportProvider.swift in Sources */,
Expand Down
20 changes: 20 additions & 0 deletions iosApp/iosApp/ComponentViews/RoutePillSection.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// RoutePillSection.swift
// iosApp
//
// Created by Horn, Melody on 2024-04-03.
// Copyright © 2024 MBTA. All rights reserved.
//

import Foundation
import shared
import SwiftUI

struct RoutePillSection<Content: View>: View {
let route: Route
let content: () -> Content

var body: some View {
Section(content: content, header: { RoutePill(route: route).padding(.leading, -20) })
}
}
32 changes: 20 additions & 12 deletions iosApp/iosApp/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ struct ContentView: View {
@StateObject var searchObserver = TextFieldObserver()
@EnvironmentObject var locationDataManager: LocationDataManager
@EnvironmentObject var alertsFetcher: AlertsFetcher
@EnvironmentObject var backendProvider: BackendProvider
@EnvironmentObject var globalFetcher: GlobalFetcher
@EnvironmentObject var nearbyFetcher: NearbyFetcher
@EnvironmentObject var predictionsFetcher: PredictionsFetcher
Expand Down Expand Up @@ -59,18 +60,19 @@ struct ContentView: View {
)
.ignoresSafeArea(edges: .bottom)
.sheet(isPresented: .constant(true)) { navigationSheet }
.searchable(
text: $searchObserver.searchText,
placement: .navigationBarDrawer(displayMode: .always),
prompt: "Find nearby transit"
).onAppear {
socketProvider.socket.connect()
Task {
try await globalFetcher.getGlobalData()
}
}
}
}.onChange(of: scenePhase) { newPhase in
}
.searchable(
text: $searchObserver.searchText,
placement: .navigationBarDrawer(displayMode: .always),
prompt: "Find nearby transit"
).onAppear {
socketProvider.socket.connect()
Task {
try await globalFetcher.getGlobalData()
}
}
.onChange(of: scenePhase) { newPhase in
if newPhase == .active {
socketProvider.socket.connect()
} else if newPhase == .background {
Expand All @@ -95,7 +97,13 @@ struct ContentView: View {
.navigationDestination(for: SheetNavigationStackEntry.self) { entry in
switch entry {
case let .stopDetails(stop, route):
StopDetailsPage(stop: stop, route: route, viewportProvider: viewportProvider)
StopDetailsPage(
backend: backendProvider.backend,
socket: socketProvider.socket,
globalFetcher: globalFetcher,
viewportProvider: viewportProvider,
stop: stop, route: route
)
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions iosApp/iosApp/Fetchers/BackendProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// BackendProvider.swift
// iosApp
//
// Created by Horn, Melody on 2024-04-03.
// Copyright © 2024 MBTA. All rights reserved.
//

import Foundation
import shared

class BackendProvider: ObservableObject {
@Published var backend: any BackendProtocol

init(backend: any BackendProtocol) {
self.backend = backend
}
}
3 changes: 3 additions & 0 deletions iosApp/iosApp/IOSApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ struct IOSApp: App {
@StateObject var locationDataManager: LocationDataManager

@StateObject var alertsFetcher: AlertsFetcher
@StateObject var backendProvider: BackendProvider
@StateObject var globalFetcher: GlobalFetcher
@StateObject var nearbyFetcher: NearbyFetcher
@StateObject var predictionsFetcher: PredictionsFetcher
Expand Down Expand Up @@ -44,6 +45,7 @@ struct IOSApp: App {
_locationDataManager = StateObject(wrappedValue: LocationDataManager(distanceFilter: 100))

_alertsFetcher = StateObject(wrappedValue: AlertsFetcher(socket: socket))
_backendProvider = StateObject(wrappedValue: BackendProvider(backend: backend))
_globalFetcher = StateObject(wrappedValue: GlobalFetcher(backend: backend))
_nearbyFetcher = StateObject(wrappedValue: NearbyFetcher(backend: backend))
_predictionsFetcher = StateObject(wrappedValue: PredictionsFetcher(socket: socket))
Expand All @@ -59,6 +61,7 @@ struct IOSApp: App {
ContentView()
.environmentObject(locationDataManager)
.environmentObject(alertsFetcher)
.environmentObject(backendProvider)
.environmentObject(globalFetcher)
.environmentObject(nearbyFetcher)
.environmentObject(predictionsFetcher)
Expand Down
13 changes: 8 additions & 5 deletions iosApp/iosApp/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
},
"Couldn't load nearby transit, unable to parse response" : {

},
"Departures" : {

},
"Detour" : {

Expand All @@ -42,6 +45,9 @@
},
"Failed to load predictions, could not connect to the server" : {

},
"Live departures" : {

},
"Loading..." : {

Expand All @@ -61,20 +67,17 @@
"No Service" : {

},
"Route: %@" : {
"Routes" : {

},
"Routes" : {
"Scheduled departures" : {

},
"Shuttle" : {

},
"Stop Closed" : {

},
"Stop: %@" : {

},
"Stops" : {

Expand Down
5 changes: 1 addition & 4 deletions iosApp/iosApp/Pages/NearbyTransit/NearbyRouteView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,10 @@ struct NearbyRouteView: View {
let now: Instant

var body: some View {
Section {
RoutePillSection(route: nearbyRoute.route) {
ForEach(nearbyRoute.patternsByStop, id: \.stop.id) { patternsAtStop in
NearbyStopView(patternsAtStop: patternsAtStop, now: now)
}
}
header: {
RoutePill(route: nearbyRoute.route).padding(.leading, -20)
}
}
}
93 changes: 78 additions & 15 deletions iosApp/iosApp/Pages/StopDetails/StopDetailsPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,93 @@

import Foundation
import shared
import SwiftPhoenixClient
import SwiftUI

struct StopDetailsPage: View {
@ObservedObject var globalFetcher: GlobalFetcher
@ObservedObject var viewportProvider: ViewportProvider

@StateObject var scheduleFetcher: ScheduleFetcher
@StateObject var predictionsFetcher: PredictionsFetcher
var stop: Stop
var route: Route?
@ObservedObject var viewportProvider: ViewportProvider
@State var now = Date.now

let timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()

init(
backend: any BackendProtocol,
socket: any PhoenixSocket,
globalFetcher: GlobalFetcher,
viewportProvider: ViewportProvider,
stop: Stop, route: Route?
) {
self.globalFetcher = globalFetcher
self.viewportProvider = viewportProvider
_scheduleFetcher = StateObject(wrappedValue: ScheduleFetcher(backend: backend))
_predictionsFetcher = StateObject(wrappedValue: PredictionsFetcher(socket: socket))
self.stop = stop
self.route = route
}

var body: some View {
Text("Stop: \(stop.name)")
.navigationTitle("Stop Details")
.onAppear {
viewportProvider.animateTo(coordinates: stop.coordinate)
VStack {
if predictionsFetcher.predictions != nil {
Text("Live departures")
} else if scheduleFetcher.schedules != nil {
Text("Scheduled departures")
} else {
Text("Departures")
}
.onChange(of: stop) { nextStop in
viewportProvider.animateTo(coordinates: nextStop.coordinate)
if let globalResponse = globalFetcher.response {
StopDetailsRoutesView(departures: StopDetailsDepartures(
stop: stop,
global: globalResponse,
schedules: scheduleFetcher.schedules,
predictions: predictionsFetcher.predictions,
filterAtTime: now.toKotlinInstant()
), now: now.toKotlinInstant())
} else {
ProgressView()
}
Text("Route: \(route?.longName ?? "-")")
}
.navigationTitle(stop.name)
.onAppear {
changeStop(stop)
}
.onChange(of: stop) { nextStop in
changeStop(nextStop)
}
.onReceive(timer) { input in
now = input
}
.onDisappear {
leavePredictions()
}
}
}

#Preview {
StopDetailsPage(
stop: ObjectCollectionBuilder.Single.shared.stop { $0.name = "Boylston" },
route: ObjectCollectionBuilder.Single.shared.route { $0.longName = "Green Line B" },
viewportProvider: ViewportProvider()
)
func changeStop(_ stop: Stop) {
getSchedule(stop)
joinPredictions(stop)
viewportProvider.animateTo(coordinates: stop.coordinate)
}

func getSchedule(_ stop: Stop) {
Task {
await scheduleFetcher.getSchedule(stopIds: [stop.id])
}
}

func joinPredictions(_ stop: Stop) {
Task {
predictionsFetcher.run(stopIds: [stop.id])
}
}

func leavePredictions() {
Task {
predictionsFetcher.leave()
}
}
}
27 changes: 27 additions & 0 deletions iosApp/iosApp/Pages/StopDetails/StopDetailsRouteView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// StopDetailsRouteView.swift
// iosApp
//
// Created by Horn, Melody on 2024-04-03.
// Copyright © 2024 MBTA. All rights reserved.
//

import Foundation
import shared
import SwiftUI

struct StopDetailsRouteView: View {
let patternsByStop: PatternsByStop
let now: Instant

var body: some View {
RoutePillSection(route: patternsByStop.route) {
ForEach(patternsByStop.patternsByHeadsign, id: \.headsign) { patternsByHeadsign in
NearbyStopRoutePatternView(
headsign: patternsByHeadsign.headsign,
predictions: patternsByHeadsign.format(now: now)
)
}
}
}
}
Loading

0 comments on commit 5b35d66

Please sign in to comment.