// // RefactoredApp.swift // LearnMapKit // // Refactored app entry point with dependency injection // import SwiftUI import ArgumentParser @main struct RefactoredLearnMapKitApp: App { private let container = DependencyContainer() init() { setupFromCommandLineArguments() } var body: some Scene { WindowGroup { MainContentView() .environmentObject(container.makeAircraftTrackingViewModel()) .environmentObject(container.configurationManager) } } private func setupFromCommandLineArguments() { guard let args = parseCommandLineArguments() else { return } Task { // Configure based on command line arguments if let hostname = args.hostname, let port = args.port { await configureNetworkMode(hostname: hostname, port: port) } else if let inputFile = args.inputfile { await configureFileMode(filePath: inputFile) } // Otherwise use default configuration } } private func parseCommandLineArguments() -> CommandLineArgs? { do { return try CommandLineArgs.parse() } catch { // If parsing fails, continue with default configuration print("Command line parsing failed: \(error)") return nil } } private func configureNetworkMode(hostname: String, port: Int) async { let networkConfig = NetworkDataSourceConfiguration(hostname: hostname, port: port) let config = AppConfiguration( dataSource: networkConfig, displaySettings: DisplaySettings(), mapSettings: MapSettings(), networkSettings: NetworkSettings() ) await container.configurationManager.updateConfiguration(config) } private func configureFileMode(filePath: String) async { let fileConfig = FileDataSourceConfiguration(filePath: filePath) let config = AppConfiguration( dataSource: fileConfig, displaySettings: DisplaySettings(), mapSettings: MapSettings(), networkSettings: NetworkSettings() ) await container.configurationManager.updateConfiguration(config) } } // MARK: - Main Content View struct MainContentView: View { @EnvironmentObject var viewModel: AircraftTrackingViewModel @EnvironmentObject var configurationManager: ConfigurationManager var body: some View { NavigationView { ZStack { AircraftMapView( aircraft: viewModel.aircraft, selectedAircraft: viewModel.selectedAircraft, mapRegion: $viewModel.mapRegion, onAircraftSelected: { aircraft in viewModel.selectAircraft(aircraft) } ) VStack { Spacer() HStack { ConnectionStatusBar( state: viewModel.connectionState, aircraftCount: viewModel.aircraftCount ) Spacer() } .padding() } if viewModel.isLoading { LoadingOverlay() } } .navigationTitle("Aircraft Tracking") .toolbar { ToolbarItemGroup(placement: .primaryAction) { ConnectionControlButton( connectionState: viewModel.connectionState, onStart: { Task { await viewModel.startTracking() } }, onStop: { Task { await viewModel.stopTracking() } }, onReconnect: { Task { await viewModel.reconnect() } } ) Button("Settings") { viewModel.showingSettings = true } } } .sheet(isPresented: $viewModel.showingSettings) { SettingsView() .environmentObject(viewModel) } .alert("Error", isPresented: .constant(viewModel.errorMessage != nil)) { Button("OK") { viewModel.clearError() } } message: { Text(viewModel.errorMessage ?? "") } } .task { // Auto-start tracking when view appears await viewModel.startTracking() } } } // MARK: - Supporting Views struct ConnectionStatusBar: View { let state: DataSourceState let aircraftCount: Int var body: some View { HStack(spacing: 12) { StatusIndicator(state: state) Text(statusText) .font(.caption) .foregroundColor(.secondary) } .padding(.horizontal, 12) .padding(.vertical, 6) .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 8)) } private var statusText: String { switch state { case .connected: return "Connected • \(aircraftCount) aircraft" case .connecting: return "Connecting..." case .disconnected: return "Disconnected" case .error(let message): return "Error: \(message)" case .idle: return "Ready" case .configuring: return "Configuring..." } } } struct StatusIndicator: View { let state: DataSourceState var body: some View { Circle() .fill(indicatorColor) .frame(width: 8, height: 8) } private var indicatorColor: Color { switch state { case .connected: return .green case .connecting, .configuring: return .orange case .disconnected, .idle: return .gray case .error: return .red } } } struct ConnectionControlButton: View { let connectionState: DataSourceState let onStart: () -> Void let onStop: () -> Void let onReconnect: () -> Void var body: some View { Button(action: buttonAction) { Image(systemName: buttonIconName) } } private var buttonIconName: String { switch connectionState { case .connected: return "stop.circle" case .connecting, .configuring: return "stop.circle" case .disconnected, .idle: return "play.circle" case .error: return "arrow.clockwise.circle" } } private func buttonAction() { switch connectionState { case .connected, .connecting, .configuring: onStop() case .disconnected, .idle: onStart() case .error: onReconnect() } } } struct LoadingOverlay: View { var body: some View { ZStack { Color.black.opacity(0.3) .ignoresSafeArea() VStack(spacing: 16) { ProgressView() .scaleEffect(1.2) Text("Connecting...") .font(.caption) .foregroundColor(.secondary) } .padding() .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 12)) } } } // MARK: - Command Line Arguments (Updated) struct CommandLineArgs: ParsableCommand { @Option(name: .shortAndLong, help: "Hostname for network mode") var hostname: String? @Option(name: .shortAndLong, help: "Port for network mode") var port: Int? @Option(name: .shortAndLong, help: "Input file path for file mode") var inputfile: String? @Flag(name: .shortAndLong, help: "Enable debug mode") var debug: Bool = false @Flag(name: .shortAndLong, help: "Show version information") var version: Bool = false }