Route map: filter from allFlights + filters internally
When the user opened the map and picked a year (e.g. 2026) in the
in-map filter sheet, the map kept drawing every flight instead of
just 2026. Root cause: the map was taking a pre-filtered `flights`
prop from HistoryView via the .sheet content closure. SwiftUI does
propagate the `filters` Binding into the sheet correctly, but it
doesn't reliably re-render the .sheet content closure with the new
pre-filtered prop value when the parent rerenders mid-presentation —
so .onChange(of: filters) fires, reset() runs, but `self.flights`
is the old (unfiltered) prop value, and the rebuilt schedule still
includes every flight.
Fix: stop relying on the parent doing the filtering. The map now
takes `allFlights` (unfiltered) and computes the displayed set
itself via `allFlights.filter { filters.matches($0) }`. Since
`filters` is a Binding that propagates cleanly, the computed set
is always in sync with whatever the user just selected in the
filter sheet — no parent-render-order race.
Also: when opening the map from HistoryView's toolbar or quick-link
card, fold the year-strip `selectedYear` into `filters.years` so
the map opens scoped to whatever the user was browsing on the home
list.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -20,13 +20,24 @@ import CoreLocation
|
||||
/// 5. Bottom drawer is a real swipe-up sheet with detents — peek
|
||||
/// shows the count + replay; expanded shows filter chips.
|
||||
struct HistoryRouteMapView: View {
|
||||
let flights: [LoggedFlight] // filtered
|
||||
let allFlights: [LoggedFlight] // unfiltered (kept for parent-API compat)
|
||||
/// The user's full unfiltered log. The map filters this set
|
||||
/// internally by `filters` so changes from the in-map filter sheet
|
||||
/// reliably re-scope the animation, even if the parent's
|
||||
/// .sheet content closure doesn't propagate a new pre-filtered
|
||||
/// array to us in time.
|
||||
let allFlights: [LoggedFlight]
|
||||
let database: AirportDatabase
|
||||
let openSky: OpenSkyClient
|
||||
let store: FlightHistoryStore
|
||||
@Binding var filters: HistoryFilters
|
||||
|
||||
/// Locally-derived "what to draw" set. Recomputed on every body
|
||||
/// pass; cheap because it's a single array filter on ~hundreds of
|
||||
/// items at most.
|
||||
private var flights: [LoggedFlight] {
|
||||
allFlights.filter { filters.matches($0) }
|
||||
}
|
||||
|
||||
@State private var position: MapCameraPosition = .automatic
|
||||
@State private var progress: Double = 0
|
||||
@State private var animationKey: Int = 0
|
||||
|
||||
@@ -102,7 +102,13 @@ struct HistoryView: View {
|
||||
}
|
||||
Section("Explore") {
|
||||
Button { showingPassport = true } label: { Label("Passport", systemImage: "book.closed") }
|
||||
Button { showingMap = true } label: { Label("Route map", systemImage: "map.fill") }
|
||||
Button {
|
||||
// Carry the year-strip scope into the map's
|
||||
// filter binding so the map opens showing
|
||||
// the same year the user was browsing.
|
||||
if let y = selectedYear { filters.years = [y] }
|
||||
showingMap = true
|
||||
} label: { Label("Route map", systemImage: "map.fill") }
|
||||
Button { showingAircraftStats = true } label: { Label("Aircraft stats", systemImage: "airplane.circle") }
|
||||
Button { showingYearInReview = true } label: { Label("Year in Review", systemImage: "sparkles") }
|
||||
}
|
||||
@@ -123,7 +129,6 @@ struct HistoryView: View {
|
||||
.sheet(isPresented: $showingMap) {
|
||||
NavigationStack {
|
||||
HistoryRouteMapView(
|
||||
flights: scoped,
|
||||
allFlights: flights,
|
||||
database: database,
|
||||
openSky: openSky,
|
||||
@@ -285,7 +290,10 @@ struct HistoryView: View {
|
||||
@ViewBuilder
|
||||
private var quickLinks: some View {
|
||||
HStack(spacing: 10) {
|
||||
quickLink(title: "Map", icon: "map.fill") { showingMap = true }
|
||||
quickLink(title: "Map", icon: "map.fill") {
|
||||
if let y = selectedYear { filters.years = [y] }
|
||||
showingMap = true
|
||||
}
|
||||
quickLink(title: "Aircraft", icon: "airplane.circle.fill") { showingAircraftStats = true }
|
||||
quickLink(title: "Year", icon: "sparkles") { showingYearInReview = true }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user