Commit Graph

4 Commits

Author SHA1 Message Date
Trey T 847e5c6035 Flight History (v1): logbook, stats, animated route map, year-in-review
Adds a new History tab implementing the core of Flighty's Passport
feature set, free + iCloud-synced.

Data layer
- `LoggedFlight` and `AirframeMetadata` @Model classes (SwiftData)
- ModelContainer with CloudKit private DB; falls back to local-only
  when CloudKit cap isn't provisioned so the app stays functional.
- `FlightHistoryStore` wraps the ModelContext for save/delete +
  dedupe + great-circle distance / duration helpers + tail-repeat
  counting.

History UI
- `HistoryView` — list grouped by year, totals strip at top, swipe
  to delete, empty state with instructions.
- `HistoryRowView` — airframe photo thumbnail (planespotters),
  flight#, route, type, date.
- `HistoryDetailView` — title → route → photo → flown-path / great-
  circle map → aircraft card (type, tail, age, "Nth time on this
  airframe") → editable notes → delete.

Add paths
- "+ Add to my flights" button on the live aircraft sheet —
  pre-fills the form from FR24 enrichment (carrier, flight#,
  route, aircraft type, tail).
- Manual entry form (`AddFlightView`) with route-explorer autofill
  via `searchSchedule(carrierCode:flightNumber:startDate:endDate:)`.
- Calendar scan (`CalendarFlightImporter` + `CalendarImportView`) —
  EventKit access prompt → regex-detect flight-shaped events
  across last 5 years → dedupe → batch-confirm with route-explorer
  enrichment.
- `WalletPassObserver` (PassKit) — observes the library for new
  boarding passes and parses origin/destination/flight#/seat.
  Service is wired; explicit UI prompt deferred to follow-up.

Stats + visualization
- `StatsEngine` — totals (flights / miles / hours / airports /
  airlines / aircraft / countries) + narrative stats (top airline,
  top route, top airport, longest, shortest, repeated tails).
- `LifetimeStatsView` — big-number tile grid + highlights cards +
  repeated airframes list.
- `HistoryRouteMapView` — every great-circle arc the user has
  flown, animating in oldest → newest on first appear. Airport
  dots sized log-scale by visit count.
- `YearInReviewView` — Spotify-Wrapped-style horizontal card deck
  for the current year: total miles, airports + countries, hours
  airborne, top airline, top route, longest flight.

Entitlements
- New `Flights.entitlements` with `iCloud.com.flights.app` CloudKit
  container.

Risk note: the build falls back to local-only SwiftData if the
CloudKit container isn't provisioned for team V3PF3M6B6U / bundle
id com.flights.app. The History feature works fully either way;
sync requires the cap to land.

Deferred to follow-ups
- Wallet auto-prompt UI binding (service exists, view hook TBD)
- Mail Share Extension (separate app-extension target)
- Jetphotos first-flight-date scraping
- OpenSky historical track replay (great-circle fallback ships)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 09:34:38 -05:00
Trey T 62729213d7 Add FlightsTests target + fix AA load fetcher (Android UA version bump)
AA was silently returning nil because the server now rejects User-Agent
"Android/2025.31" with HTTP 403 ("Please update your version of the
American Airlines app"). Bumped to "2026.14" (matches the APK in
airlines/) and centralized to a constant so the next bump is one line.
Added comprehensive logging to fetchAmericanLoad (was zero) so the next
breakage won't be silent — including an explicit ⚠️ when the server
returns the "update your version" payload.

New FlightsTests target with AirlineLoadIntegrationTests — hits live
airline APIs to verify each fetcher still returns data. Per-airline
strategy:
- Try route-explorer /departures from carrier hubs for a flight in the
  next 24h (works for AA/UA/AS/B6).
- Fall back to a known-good daily flight when route-explorer doesn't
  have the carrier in its data (NK/EK/KE — ULCC + some intl carriers).
- B6/EK/NK are status-only by design (no standby data without a PNR);
  asserted as non-nil only.
- XE (JSX) skipped: needs WKWebView host.

Retries on route-explorer 429 by parsing the `retryAfter` field and
sleeping the indicated number of seconds. Static-shared client+services
across tests so the token cache survives.

Results 2026-05-26 (xcodebuild test -scheme Flights):
   AA, AS, B6, EK, KE, UA   NK  ⏭️ XE
NK (Spirit) is now broken: GetFlightInfoBI returns HTTP 403 with
{"getFlightInfoBIResult":null}. APIM key still accepted (401 without
it), but the call itself is rejected. Documented in
AIRLINE_INTEGRATION_GUIDE.md as a known regression to fix; likely
needs reverse-engineering against the current Spirit APK in airlines/.

Also: enable shared schemes in .gitignore so `xcodebuild test` works
out of the box for anyone cloning the repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 14:14:09 -05:00
Trey t 6005146e75 Airline integration work: AirlineLoadService updates, docs, JSX scripts
- AirlineLoadService: pass airport DB for timezone-aware date strings,
  add browser-shaped headers for United, expand JetBlue/Alaska/Emirates
  signatures to take origin, log/parse fixes for Korean Air.
- FlightsApp: build AirlineLoadService with the airport DB and inject it.
- JSX: continued WebView-based fetcher work plus updated JSX_NOTES.
- Docs: add AIRLINE_INTEGRATION_GUIDE.md, drop the old AIRLINE_API_SPEC.md,
  add api_docs/ (StaffTraveler reverse-engineering captures + findings).
- Scripts: jsx_cdp_probe, jsx_live_monitor, jsx_swift_smoke for JSX
  protocol exploration.
- .gitignore: exclude airlines/ (local-only APK/IPA reverse-engineering).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 23:21:30 -05:00
Trey t 3790792040 Initial commit: Flights iOS app
Flight search app built on FlightConnections.com API data.
Features: airport search with autocomplete, browse by country/state/map,
flight schedules by route and date, multi-airline support with per-airline
schedule loading. Includes 4,561-airport GPS database for map browsing.
Adaptive light/dark mode UI inspired by Flighty.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:01:07 -05:00