Live map: center on user, persist region, zoom-based aircraft cap

- Initial region cascade: restore last viewed region → on location
  grant, animate to a city-level view centered on user; otherwise
  fall back to the saved/continental default. User pans are detected
  via a center-delta threshold so a late location grant doesn't yank
  the camera away from where the user is looking.
- LocationService: thin one-shot CLLocationManager wrapper with
  CheckedContinuation. Added NSLocationWhenInUseUsageDescription via
  INFOPLIST_KEY_ build setting.
- Visible-aircraft cap scales with zoom (<2°: uncapped, <8°: 100,
  <25°: 150, else 200). Active filters bypass the cap entirely so
  every match always renders. When capped, we keep the N closest to
  the map center.
- Footer shows "Showing N of M" when the cap clips, "N aircraft"
  otherwise.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Trey T
2026-05-27 07:37:34 -05:00
parent de7a70b198
commit dee6df1ac6
3 changed files with 225 additions and 3 deletions
+6
View File
@@ -58,6 +58,7 @@
LVAA000AAAA000AAAA000001 /* AircraftDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = LVAA000AAAA000AAAA000002 /* AircraftDatabase.swift */; };
LVBB000BBBB000BBBB000001 /* LiveFilterPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = LVBB000BBBB000BBBB000002 /* LiveFilterPicker.swift */; };
LVCC000CCCC000CCCC000001 /* aircraftDB.json in Resources */ = {isa = PBXBuildFile; fileRef = LVCC000CCCC000CCCC000002 /* aircraftDB.json */; };
LVDD000DDDD000DDDD000001 /* LocationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = LVDD000DDDD000DDDD000002 /* LocationService.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -124,6 +125,7 @@
LVAA000AAAA000AAAA000002 /* AircraftDatabase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AircraftDatabase.swift; sourceTree = "<group>"; };
LVBB000BBBB000BBBB000002 /* LiveFilterPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveFilterPicker.swift; sourceTree = "<group>"; };
LVCC000CCCC000CCCC000002 /* aircraftDB.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = aircraftDB.json; sourceTree = "<group>"; };
LVDD000DDDD000DDDD000002 /* LocationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationService.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -243,6 +245,7 @@
LV3300003333000033330002 /* AircraftRegistry.swift */,
LV7700007777000077770002 /* OpenSkyCredentials.swift */,
LVAA000AAAA000AAAA000002 /* AircraftDatabase.swift */,
LVDD000DDDD000DDDD000002 /* LocationService.swift */,
);
path = Services;
sourceTree = "<group>";
@@ -414,6 +417,7 @@
LV8800008888000088880001 /* OpenSkySettingsView.swift in Sources */,
LVAA000AAAA000AAAA000001 /* AircraftDatabase.swift in Sources */,
LVBB000BBBB000BBBB000001 /* LiveFilterPicker.swift in Sources */,
LVDD000DDDD000DDDD000001 /* LocationService.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -437,6 +441,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = V3PF3M6B6U;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Show your current location on the live flight map so you can quickly see aircraft overhead.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
@@ -466,6 +471,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = V3PF3M6B6U;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Show your current location on the live flight map so you can quickly see aircraft overhead.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;