| Code | What It Does | How It Does It |
| ▶ IMPORTS | | |
| import SwiftUI
import CoreLocation | Framework imports | Imports SwiftUI, CoreLocation. |
| ▶ SUB-VIEWS | | |
| private struct BusRouteBadge: View {
let route: String
var body: some View {
Text(route)
.font(.system(size: 9, weight: .bold))
.foregroundColor(.white)
.padding(.horizontal, 5)
.padding(.vertical, 3)
.background(watchBusRouteColor(for: route), in: RoundedRectangle(cornerRadius: 5))
}
} | `BusRouteBadge` struct | Defines the `BusRouteBadge` struct. Conforms to View. |
| private struct BusArrivalRow: View {
let arrival: WatchBusArrival
var body: some View {
HStack(spacing: 6) {
BusRouteBadge(route: arrival.route)
Text(arrival.headsign)
.font(.system(size: 11))
.foregroundColor(.white.opacity(0.85))
.lineLimit(1)
Spacer(minLength: 2)
Text(arrival.label)
.font(.system(size: 13, weight: .semibold))
.foregroundColor(.white)
.frame(minWidth: 28, alignment: .trailing)
Text("min")
.font(.system(size: 10))
.foregroundColor(.white.opacity(0.6))
}
}
} | `BusArrivalRow` struct | Defines the `BusArrivalRow` struct. Conforms to View. |
| private struct BusStopBlock: View {
let stop: WatchNearbyBusStop
var body: some View {
VStack(alignment: .leading, spacing: 6) {
Text(stop.name)
.font(.system(size: 13, weight: .bold))
.foregroundColor(.white)
.lineLimit(2)
.fixedSize(horizontal: false, vertical: true)
VStack(spacing: 4) {
ForEach(stop.arrivals.prefix(4)) { arrival in
BusArrivalRow(arrival: arrival)
}
}
}
.padding(.horizontal, 10)
.padding(.vertical, 8)
.background(RoundedRectangle(cornerRadius: 10).fill(Color.white.opacity(0.08)))
}
} | `BusStopBlock` struct | Defines the `BusStopBlock` struct. Conforms to View. |
| ▶ MAIN VIEW | | |
| struct WatchBusView: View {
@EnvironmentObject var store: WatchEntryStore
@StateObject private var service = WatchBusArrivalsService.shared
var body: some View {
Group {
if service.isLoading && service.stops.isEmpty {
VStack(spacing: 8) {
ProgressView()
Text("Finding nearby buses…")
.font(.caption2)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
}
} else if let err = service.errorMessage {
VStack(spacing: 6) {
Image(systemName: "exclamationmark.triangle").foregroundColor(.orange)
Text(err).font(.caption2).foregroundColor(.secondary)
.multilineTextAlignment(.center)
Button("Retry") { Task { await fetchIfLocation() } }.font(.caption2)
}
} else if service.stops.isEmpty {
VStack(spacing: 6) {
Image(systemName: "location.slash").foregroundColor(.secondary)
Text("No nearby bus stops found")
.font(.caption2).foregroundColor(.secondary)
.multilineTextAlignment(.center)
}
} else {
ScrollView {
VStack(alignment: .leading, spacing: 12) {
ForEach(service.stops) { stop in
BusStopBlock(stop: stop)
}
}
.padding(.horizontal, 4)
.padding(.vertical, 6)
}
}
}
.navigationTitle("Buses")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button { Task { await fetchIfLocation() } } label: {
Image(systemName: "arrow.clockwise")
.font(.system(size: 14, weight: .medium))
}
}
}
.task {
while !Task.isCancelled {
let start = Date()
await fetchIfLocation()
let elapsed = Date().timeIntervalSince(start)
let remaining = max(0, 30 - elapsed)
try? await Task.sleep(for: .seconds(remaining))
}
}
}
private func fetchIfLocation() async {
store.startLocationIfNeeded()
var waited = 0
while store.userLocation == nil && waited < 10 {
try? await Task.sleep(nanoseconds: 500_000_000)
waited += 1
}
let loc = store.userLocation ?? CLLocation(latitude: 40.7128, longitude: -74.0060)
await service.refresh(near: loc)
}
} | `WatchBusView` struct | Defines the `WatchBusView` struct. Conforms to View. |
| #Preview {
NavigationStack { WatchBusView() }
.environmentObject(WatchEntryStore())
} | Code block | See source code for full implementation. |