fix: 14 audit fixes — concurrency, memory, performance, accessibility
Second audit round addressing data races, task stacking, unbounded caches, and VoiceOver gaps across 7 files. Concurrency: - Move NSItemProvider @State access into MainActor block (3 drop handlers) - Cancel stale ScheduleViewModel tasks on rapid filter changes Memory: - Replace unbounded image dict with LRUCache(countLimit: 50) - Replace demo-mode asyncAfter with cancellable Task Performance: - Wrap debug NBA print() in #if DEBUG - Cache visitsById via @State + onChange instead of per-render computed - Pre-compute sportProgressFractions in ProgressViewModel - Replace allGames computed property with hasGames bool check - Cache sortedTrips via @State + onChange in SavedTripsListView Accessibility: - Add combined VoiceOver label to progress ring - Combine away/home team text into single readable phrase - Hide decorative StadiumDetailSheet icon from VoiceOver - Add explicit accessibilityLabel to SportFilterChip - Add combined accessibilityLabel to GameRowView Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -479,10 +479,7 @@ struct SavedTripsListView: View {
|
||||
@State private var showDebugPoll = false
|
||||
#endif
|
||||
|
||||
/// Trips sorted by most cities (stops) first
|
||||
private var sortedTrips: [SavedTrip] {
|
||||
trips.sorted { ($0.trip?.stops.count ?? 0) > ($1.trip?.stops.count ?? 0) }
|
||||
}
|
||||
@State private var sortedTrips: [SavedTrip] = []
|
||||
|
||||
/// Trips as domain objects for poll creation
|
||||
private var tripsForPollCreation: [Trip] {
|
||||
@@ -501,6 +498,9 @@ struct SavedTripsListView: View {
|
||||
.padding(Theme.Spacing.md)
|
||||
}
|
||||
.themedBackground()
|
||||
.onChange(of: trips, initial: true) { _, newTrips in
|
||||
sortedTrips = newTrips.sorted { ($0.trip?.stops.count ?? 0) > ($1.trip?.stops.count ?? 0) }
|
||||
}
|
||||
.task {
|
||||
guard !hasLoadedPolls else { return }
|
||||
hasLoadedPolls = true
|
||||
|
||||
Reference in New Issue
Block a user