Skip to content

Commit

Permalink
Merge branch 'refs/heads/main' into kb-xcode-16-bumps
Browse files Browse the repository at this point in the history
  • Loading branch information
boringcactus committed Oct 16, 2024
2 parents a390dee + a92d47b commit 5308b5c
Show file tree
Hide file tree
Showing 55 changed files with 880 additions and 476 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ class NearbyTransitPageTest : KoinTest {

override var lastUpdated: Instant? = null

override fun shouldForgetPredictions(predictionCount: Int) = false

override fun disconnect() {
/* no-op */
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ class NearbyTransitViewTest : KoinTest {

override var lastUpdated: Instant? = null

override fun shouldForgetPredictions(predictionCount: Int) = false

override fun disconnect() {
/* no-op */
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ class StopDetailsViewTest {

override var lastUpdated: Instant? = null

override fun shouldForgetPredictions(predictionCount: Int) = false

override fun disconnect() {
/* no-op */
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class SubscribeToPredictionsTest {

override var lastUpdated: Instant? = null

override fun shouldForgetPredictions(predictionCount: Int) = false

override fun disconnect() {
check(isConnected) { "called disconnect when not connected" }
isConnected = false
Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ androidx-navigationCompose = "2.8.1"
agp = "8.5.2"
# see https://developer.android.com/develop/ui/compose/bom/bom-mapping
# and https://developer.android.com/jetpack/androidx/releases/compose for release notes
compose-bom = "2024.09.00"
compose-bom = "2024.09.03"
datastorePreferencesCore = "1.1.1"
kotlin = "2.0.20"
javaphoenixclient = "1.3.1"
Expand All @@ -18,7 +18,7 @@ mapbox = "11.3.0"
mapboxTurf = "6.15.0"
mokkery = "2.3.0"
okhttp = "4.12.0"
okio = "3.9.0"
okio = "3.9.1"
sentry = "0.9.0"
skie = "0.9.2"
spatialk = "0.3.0"
Expand Down
45 changes: 30 additions & 15 deletions iosApp/iosApp/ComponentViews/ErrorBanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ struct ErrorBanner: View {
var repo: IErrorBannerStateRepository
@State var state: ErrorBannerState?

let loadingWhenPredictionsStale: Bool

let inspection = Inspection<Self>()

init(repo: IErrorBannerStateRepository = RepositoryDI().errorBanner) {
init(loadingWhenPredictionsStale: Bool, repo: IErrorBannerStateRepository = RepositoryDI().errorBanner) {
self.loadingWhenPredictionsStale = loadingWhenPredictionsStale
self.repo = repo
state = repo.state.value
}
Expand All @@ -42,17 +45,21 @@ struct ErrorBanner: View {
}))
}
case let .stalePredictions(state):
IconCard(
iconName: "clock.arrow.circlepath",
details: Text("Updated \(state.minutesAgo(), specifier: "%ld") minutes ago")
) {
AnyView(Button(action: {
repo.clearState()
state.action()
}, label: {
Image(systemName: "arrow.clockwise")
.accessibilityLabel("Refresh predictions")
}))
if loadingWhenPredictionsStale {
ProgressView()
} else {
IconCard(
iconName: "clock.arrow.circlepath",
details: Text("Updated \(state.minutesAgo(), specifier: "%ld") minutes ago")
) {
AnyView(Button(action: {
repo.clearState()
state.action()
}, label: {
Image(systemName: "arrow.clockwise")
.accessibilityLabel("Refresh predictions")
}))
}
}
case nil:
// for some reason, .collect on an EmptyView doesn't work
Expand All @@ -62,7 +69,15 @@ struct ErrorBanner: View {
}

#Preview {
ErrorBanner(repo: MockErrorBannerStateRepository(
state: .StalePredictions(lastUpdated: Date.now.addingTimeInterval(-2 * 60).toKotlinInstant(), action: {})
))
VStack(spacing: 16) {
ErrorBanner(loadingWhenPredictionsStale: false, repo: MockErrorBannerStateRepository(
state: .DataError(action: {})
))
ErrorBanner(loadingWhenPredictionsStale: false, repo: MockErrorBannerStateRepository(
state: .StalePredictions(lastUpdated: Date.now.addingTimeInterval(-2 * 60).toKotlinInstant(), action: {})
))
ErrorBanner(loadingWhenPredictionsStale: true, repo: MockErrorBannerStateRepository(
state: .StalePredictions(lastUpdated: Date.now.addingTimeInterval(-2 * 60).toKotlinInstant(), action: {})
))
}
}
2 changes: 1 addition & 1 deletion iosApp/iosApp/ContentView.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import CoreLocation
@_spi(Experimental) import MapboxMaps
import shared
import SwiftPhoenixClient
import SwiftUI
@_spi(Experimental) import MapboxMaps

struct ContentView: View {
@Environment(\.scenePhase) private var scenePhase
Expand Down
2 changes: 1 addition & 1 deletion iosApp/iosApp/ContentViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
//

import Foundation
import shared
@_spi(Experimental) import MapboxMaps
import shared

class ContentViewModel: ObservableObject {
@Published var configResponse: ApiResult<ConfigResponse>?
Expand Down
3 changes: 1 addition & 2 deletions iosApp/iosApp/Fetchers/ViewportProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
//

import Combine
import shared
import SwiftUI
@_spi(Experimental) import MapboxMaps
import shared
import SwiftUI

class ViewportProvider: ObservableObject {
enum Defaults {
Expand Down
3 changes: 3 additions & 0 deletions iosApp/iosApp/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@
},
"select location" : {

},
"Service Change" : {
"comment" : "Possible alert effect"
},
"Service ended" : {

Expand Down
1 change: 1 addition & 0 deletions iosApp/iosApp/Pages/AlertDetails/AlertDetails.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct AlertDetails: View {
switch alert.effect {
case .detour: NSLocalizedString("Detour", comment: "Possible alert effect")
case .dockClosure: NSLocalizedString("Dock Closure", comment: "Possible alert effect")
case .serviceChange: NSLocalizedString("Service Change", comment: "Possible alert effect")
case .shuttle: NSLocalizedString("Shuttle", comment: "Possible alert effect")
case .stationClosure: NSLocalizedString("Station Closure", comment: "Possible alert effect")
case .stopClosure: NSLocalizedString("Stop Closure", comment: "Possible alert effect")
Expand Down
15 changes: 13 additions & 2 deletions iosApp/iosApp/Pages/Map/AnnotatedMap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
// Copyright © 2024 MBTA. All rights reserved.
//

@_spi(Experimental) import MapboxMaps
import shared
import SwiftUI
@_spi(Experimental) import MapboxMaps

struct AnnotatedMap: View {
static let annotationTextZoomThreshold = 19.0
Expand All @@ -28,6 +28,7 @@ struct AnnotatedMap: View {

@ObservedObject var viewportProvider: ViewportProvider
@Environment(\.colorScheme) var colorScheme
@Environment(\.scenePhase) var scenePhase

var handleCameraChange: (CameraChanged) -> Void
var handleStyleLoaded: () -> Void
Expand All @@ -53,13 +54,18 @@ struct AnnotatedMap: View {
// The initial run of this happens before any required data is loaded, so it does nothing and
// handleTryLayerInit always performs the first layer creation, but once the data is in place,
// this handles any time the map is reloaded again, like for a light/dark mode switch.
handleStyleLoaded()
if scenePhase == .active {
// onStyleLoaded was unexpectedly called when app moved to background because the colorScheme
// changes twice while backgrounding. Ensure it is only called when the app is active.
handleStyleLoaded()
}
}
.additionalSafeAreaInsets(.bottom, sheetHeight)
.accessibilityIdentifier("transitMap")
.onReceive(viewportProvider.cameraStatePublisher) { newCameraState in
zoomLevel = newCameraState.zoom
}
.withScenePhaseHandlers(onActive: onActive)
.task {
do {
mapDebug = try await getSettingUsecase.execute(setting: .map).boolValue
Expand All @@ -69,6 +75,11 @@ struct AnnotatedMap: View {
}
}

func onActive() {
// re-load styles in case the colorScheme changed while in the background
handleStyleLoaded()
}

private var allVehicles: [Vehicle]? {
switch (vehicles, selectedVehicle) {
case (.none, .none): nil
Expand Down
2 changes: 1 addition & 1 deletion iosApp/iosApp/Pages/Map/AnnotationLabel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
// Copyright © 2024 MBTA. All rights reserved.
//

import SwiftUI
@_spi(Experimental) import MapboxMaps
import SwiftUI

extension View {
func annotationLabel<Content: View>(_ content: Content) -> ModifiedContent<Self, FloatingLabel<Content>> {
Expand Down
4 changes: 1 addition & 3 deletions iosApp/iosApp/Pages/Map/HomeMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
// Copyright © 2024 MBTA. All rights reserved.
//

@_spi(Experimental) import MapboxMaps
import os
import shared
import SwiftUI
@_spi(Experimental) import MapboxMaps

struct HomeMapView: View {
var analytics: NearbyTransitAnalytics = AnalyticsProvider.shared
Expand All @@ -34,8 +34,6 @@ struct HomeMapView: View {
@State var vehiclesRepository: IVehiclesRepository
@State var vehiclesData: [Vehicle]?

@State var upcomingRoutePatterns: Set<String> = .init()

@StateObject var locationDataManager: LocationDataManager
@Binding var sheetHeight: CGFloat

Expand Down
6 changes: 4 additions & 2 deletions iosApp/iosApp/Pages/Map/HomeMapViewHandlerExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
// Copyright © 2024 MBTA. All rights reserved.
//

@_spi(Experimental) import MapboxMaps
import shared
import SwiftUI
@_spi(Experimental) import MapboxMaps

/*
Functions for handling interactions with the map, like prop change, navigation, and tapping.
Expand Down Expand Up @@ -101,7 +101,9 @@ extension HomeMapView {
leaveVehiclesChannel()
vehiclesRepository.connect(routeId: routeId, directionId: directionId) { outcome in
if case let .ok(result) = onEnum(of: outcome) {
vehiclesData = Array(result.data.vehicles.values)
if let departures = nearbyVM.departures {
vehiclesData = Array(departures.filterVehiclesByUpcoming(vehicles: result.data).values)
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions iosApp/iosApp/Pages/Map/HomeMapViewLayerExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
// Copyright © 2024 MBTA. All rights reserved.
//

@_spi(Experimental) import MapboxMaps
import shared
import SwiftUI
@_spi(Experimental) import MapboxMaps

/*
Functions for manipulating the layers displayed on the map.
Expand Down Expand Up @@ -60,13 +60,13 @@ extension HomeMapView {

func refreshMap() {
if let layerManager = mapVM.layerManager {
updateGlobalMapDataSources()
if layerManager.currentScheme != colorScheme {
layerManager.addIcons(recreate: true)
addLayers(layerManager, recreate: true)
} else {
addLayers(layerManager)
}
updateGlobalMapDataSources()
}
}

Expand Down
13 changes: 10 additions & 3 deletions iosApp/iosApp/Pages/Map/MapLayerManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
// Copyright © 2024 MBTA. All rights reserved.
//

@_spi(Experimental) import MapboxMaps
import os
import shared
import SwiftUI
@_spi(Experimental) import MapboxMaps

protocol IMapLayerManager {
var currentScheme: ColorScheme? { get }
Expand Down Expand Up @@ -56,6 +56,13 @@ class MapLayerManager: IMapLayerManager {
}
}

/*
Adds persistent layers so that they are persisted even if the underlying map style changes. To intentionally
re-create the layers due to a change that corresponds with a style change (such as colorScheme changing),
set recreate to true.
https://docs.mapbox.com/ios/maps/api/11.5.0/documentation/mapboxmaps/stylemanager/addpersistentlayer(_:layerposition:)
*/
func addLayers(colorScheme: ColorScheme, recreate: Bool = false) {
let colorPalette = getColorPalette(colorScheme: colorScheme)
currentScheme = colorScheme
Expand All @@ -76,9 +83,9 @@ class MapLayerManager: IMapLayerManager {
}

if map.layerExists(withId: "puck") {
try map.addLayer(layer, layerPosition: .below("puck"))
try map.addPersistentLayer(layer, layerPosition: .below("puck"))
} else {
try map.addLayer(layer)
try map.addPersistentLayer(layer)
}
} catch {
Logger().error("Failed to add layer \(layer.id)\n\(error)")
Expand Down
2 changes: 1 addition & 1 deletion iosApp/iosApp/Pages/Map/MapViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import Combine
import Foundation
import shared
@_spi(Experimental) import MapboxMaps
import shared

class MapViewModel: ObservableObject {
@Published var selectedVehicle: Vehicle?
Expand Down
6 changes: 4 additions & 2 deletions iosApp/iosApp/Pages/NearbyTransit/NearbyTransitPageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@

import Combine
import CoreLocation
@_spi(Experimental) import MapboxMaps
import os
import shared
import SwiftUI
@_spi(Experimental) import MapboxMaps

struct NearbyTransitPageView: View {
@ObservedObject var nearbyVM: NearbyViewModel
@ObservedObject var viewportProvider: ViewportProvider

@State var location: CLLocationCoordinate2D?
@State var isReturningFromBackground = false

let inspection = Inspection<Self>()

Expand All @@ -34,7 +35,7 @@ struct NearbyTransitPageView: View {
Color.fill1.ignoresSafeArea(.all)
VStack {
SheetHeader(title: String(localized: "Nearby Transit", comment: "Header for nearby transit sheet"))
ErrorBanner()
ErrorBanner(loadingWhenPredictionsStale: isReturningFromBackground)
if viewportProvider.isManuallyCentering {
LoadingCard { Text("select location") }
} else {
Expand All @@ -44,6 +45,7 @@ struct NearbyTransitPageView: View {
},
state: $nearbyVM.nearbyState,
location: $location,
isReturningFromBackground: $isReturningFromBackground,
nearbyVM: nearbyVM
)

Expand Down
Loading

0 comments on commit 5308b5c

Please sign in to comment.