Remove debug prints and fix build warnings
- Remove all print statements from planning engine, data providers, and PDF generation - Fix deprecated CLGeocoder usage with MKLocalSearch for iOS 26 - Fix Swift 6 actor isolation by converting PDFGenerator/ExportService to @MainActor - Add @retroactive to CLLocationCoordinate2D protocol conformances - Fix unused variable warnings in GameDAGRouter and scenario planners - Remove unreachable catch blocks in SettingsViewModel 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -88,11 +88,9 @@ final class ScheduleViewModel {
|
||||
} catch let cloudKitError as CloudKitError {
|
||||
self.error = cloudKitError
|
||||
self.errorMessage = cloudKitError.errorDescription
|
||||
print("CloudKit error loading games: \(cloudKitError.errorDescription ?? "Unknown")")
|
||||
} catch {
|
||||
self.error = error
|
||||
self.errorMessage = error.localizedDescription
|
||||
print("Failed to load games: \(error)")
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
|
||||
@@ -78,15 +78,11 @@ final class SettingsViewModel {
|
||||
isSyncing = true
|
||||
syncError = nil
|
||||
|
||||
do {
|
||||
// Trigger data reload from provider
|
||||
await AppDataProvider.shared.loadInitialData()
|
||||
// Trigger data reload from provider
|
||||
await AppDataProvider.shared.loadInitialData()
|
||||
|
||||
lastSyncDate = Date()
|
||||
UserDefaults.standard.set(lastSyncDate, forKey: "lastSyncDate")
|
||||
} catch {
|
||||
syncError = error.localizedDescription
|
||||
}
|
||||
lastSyncDate = Date()
|
||||
UserDefaults.standard.set(lastSyncDate, forKey: "lastSyncDate")
|
||||
|
||||
isSyncing = false
|
||||
}
|
||||
|
||||
@@ -222,128 +222,121 @@ final class TripCreationViewModel {
|
||||
|
||||
viewState = .planning
|
||||
|
||||
do {
|
||||
// Mode-specific setup
|
||||
var effectiveStartDate = startDate
|
||||
var effectiveEndDate = endDate
|
||||
var resolvedStartLocation: LocationInput?
|
||||
var resolvedEndLocation: LocationInput?
|
||||
// Mode-specific setup
|
||||
var effectiveStartDate = startDate
|
||||
var effectiveEndDate = endDate
|
||||
var resolvedStartLocation: LocationInput?
|
||||
var resolvedEndLocation: LocationInput?
|
||||
|
||||
switch planningMode {
|
||||
case .dateRange:
|
||||
// Use provided date range, no location needed
|
||||
// Games will be found within the date range across all regions
|
||||
effectiveStartDate = startDate
|
||||
effectiveEndDate = endDate
|
||||
switch planningMode {
|
||||
case .dateRange:
|
||||
// Use provided date range, no location needed
|
||||
// Games will be found within the date range across all regions
|
||||
effectiveStartDate = startDate
|
||||
effectiveEndDate = endDate
|
||||
|
||||
case .gameFirst:
|
||||
// Calculate date range from selected games + buffer
|
||||
if let dateRange = gameFirstDateRange {
|
||||
effectiveStartDate = dateRange.start
|
||||
effectiveEndDate = dateRange.end
|
||||
}
|
||||
// Derive start/end locations from first/last game stadiums
|
||||
if let firstGame = selectedGames.sorted(by: { $0.game.dateTime < $1.game.dateTime }).first,
|
||||
let lastGame = selectedGames.sorted(by: { $0.game.dateTime < $1.game.dateTime }).last {
|
||||
resolvedStartLocation = LocationInput(
|
||||
name: firstGame.stadium.city,
|
||||
coordinate: firstGame.stadium.coordinate,
|
||||
address: "\(firstGame.stadium.city), \(firstGame.stadium.state)"
|
||||
)
|
||||
resolvedEndLocation = LocationInput(
|
||||
name: lastGame.stadium.city,
|
||||
coordinate: lastGame.stadium.coordinate,
|
||||
address: "\(lastGame.stadium.city), \(lastGame.stadium.state)"
|
||||
)
|
||||
}
|
||||
|
||||
case .locations:
|
||||
// Resolve provided locations
|
||||
await resolveLocations()
|
||||
resolvedStartLocation = startLocation
|
||||
resolvedEndLocation = endLocation
|
||||
|
||||
guard resolvedStartLocation != nil, resolvedEndLocation != nil else {
|
||||
viewState = .error("Could not resolve start or end location")
|
||||
return
|
||||
}
|
||||
case .gameFirst:
|
||||
// Calculate date range from selected games + buffer
|
||||
if let dateRange = gameFirstDateRange {
|
||||
effectiveStartDate = dateRange.start
|
||||
effectiveEndDate = dateRange.end
|
||||
}
|
||||
// Derive start/end locations from first/last game stadiums
|
||||
if let firstGame = selectedGames.sorted(by: { $0.game.dateTime < $1.game.dateTime }).first,
|
||||
let lastGame = selectedGames.sorted(by: { $0.game.dateTime < $1.game.dateTime }).last {
|
||||
resolvedStartLocation = LocationInput(
|
||||
name: firstGame.stadium.city,
|
||||
coordinate: firstGame.stadium.coordinate,
|
||||
address: "\(firstGame.stadium.city), \(firstGame.stadium.state)"
|
||||
)
|
||||
resolvedEndLocation = LocationInput(
|
||||
name: lastGame.stadium.city,
|
||||
coordinate: lastGame.stadium.coordinate,
|
||||
address: "\(lastGame.stadium.city), \(lastGame.stadium.state)"
|
||||
)
|
||||
}
|
||||
|
||||
// Ensure we have games data
|
||||
if games.isEmpty {
|
||||
await loadScheduleData()
|
||||
case .locations:
|
||||
// Resolve provided locations
|
||||
await resolveLocations()
|
||||
resolvedStartLocation = startLocation
|
||||
resolvedEndLocation = endLocation
|
||||
|
||||
guard resolvedStartLocation != nil, resolvedEndLocation != nil else {
|
||||
viewState = .error("Could not resolve start or end location")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure we have games data
|
||||
if games.isEmpty {
|
||||
await loadScheduleData()
|
||||
}
|
||||
|
||||
// Read max trip options from settings (default 10)
|
||||
let savedMaxOptions = UserDefaults.standard.integer(forKey: "maxTripOptions")
|
||||
let maxTripOptions = savedMaxOptions > 0 ? min(20, savedMaxOptions) : 10
|
||||
|
||||
// Build preferences
|
||||
let preferences = TripPreferences(
|
||||
planningMode: planningMode,
|
||||
startLocation: resolvedStartLocation,
|
||||
endLocation: resolvedEndLocation,
|
||||
sports: selectedSports,
|
||||
mustSeeGameIds: mustSeeGameIds,
|
||||
travelMode: travelMode,
|
||||
startDate: effectiveStartDate,
|
||||
endDate: effectiveEndDate,
|
||||
numberOfStops: useStopCount ? numberOfStops : nil,
|
||||
tripDuration: useStopCount ? nil : tripDurationDays,
|
||||
leisureLevel: leisureLevel,
|
||||
mustStopLocations: mustStopLocations,
|
||||
preferredCities: preferredCities,
|
||||
routePreference: routePreference,
|
||||
needsEVCharging: needsEVCharging,
|
||||
lodgingType: lodgingType,
|
||||
numberOfDrivers: numberOfDrivers,
|
||||
maxDrivingHoursPerDriver: maxDrivingHoursPerDriver,
|
||||
maxTripOptions: maxTripOptions
|
||||
)
|
||||
|
||||
// Build planning request
|
||||
let request = PlanningRequest(
|
||||
preferences: preferences,
|
||||
availableGames: games,
|
||||
teams: teams,
|
||||
stadiums: stadiums
|
||||
)
|
||||
|
||||
// Plan the trip
|
||||
let result = planningEngine.planItineraries(request: request)
|
||||
|
||||
switch result {
|
||||
case .success(var options):
|
||||
guard !options.isEmpty else {
|
||||
viewState = .error("No valid itinerary found")
|
||||
return
|
||||
}
|
||||
|
||||
// Read max trip options from settings (default 10)
|
||||
let savedMaxOptions = UserDefaults.standard.integer(forKey: "maxTripOptions")
|
||||
let maxTripOptions = savedMaxOptions > 0 ? min(20, savedMaxOptions) : 10
|
||||
|
||||
// Build preferences
|
||||
let preferences = TripPreferences(
|
||||
planningMode: planningMode,
|
||||
startLocation: resolvedStartLocation,
|
||||
endLocation: resolvedEndLocation,
|
||||
sports: selectedSports,
|
||||
mustSeeGameIds: mustSeeGameIds,
|
||||
travelMode: travelMode,
|
||||
startDate: effectiveStartDate,
|
||||
endDate: effectiveEndDate,
|
||||
numberOfStops: useStopCount ? numberOfStops : nil,
|
||||
tripDuration: useStopCount ? nil : tripDurationDays,
|
||||
leisureLevel: leisureLevel,
|
||||
mustStopLocations: mustStopLocations,
|
||||
preferredCities: preferredCities,
|
||||
routePreference: routePreference,
|
||||
needsEVCharging: needsEVCharging,
|
||||
lodgingType: lodgingType,
|
||||
numberOfDrivers: numberOfDrivers,
|
||||
maxDrivingHoursPerDriver: maxDrivingHoursPerDriver,
|
||||
maxTripOptions: maxTripOptions
|
||||
)
|
||||
|
||||
// Build planning request
|
||||
let request = PlanningRequest(
|
||||
preferences: preferences,
|
||||
availableGames: games,
|
||||
teams: teams,
|
||||
stadiums: stadiums
|
||||
)
|
||||
|
||||
// Plan the trip
|
||||
let result = planningEngine.planItineraries(request: request)
|
||||
|
||||
switch result {
|
||||
case .success(var options):
|
||||
guard !options.isEmpty else {
|
||||
viewState = .error("No valid itinerary found")
|
||||
return
|
||||
}
|
||||
|
||||
// Enrich with EV chargers if requested and feature is enabled
|
||||
if FeatureFlags.enableEVCharging && needsEVCharging {
|
||||
print("[TripCreation] Enriching \(options.count) options with EV chargers...")
|
||||
options = await ItineraryBuilder.enrichWithEVChargers(options)
|
||||
print("[TripCreation] EV charger enrichment complete")
|
||||
}
|
||||
|
||||
// Store preferences for later conversion
|
||||
currentPreferences = preferences
|
||||
|
||||
if options.count == 1 {
|
||||
// Only one option - go directly to detail
|
||||
let trip = convertToTrip(option: options[0], preferences: preferences)
|
||||
viewState = .completed(trip)
|
||||
} else {
|
||||
// Multiple options - show selection view
|
||||
viewState = .selectingOption(options)
|
||||
}
|
||||
|
||||
case .failure(let failure):
|
||||
viewState = .error(failureMessage(for: failure))
|
||||
// Enrich with EV chargers if requested and feature is enabled
|
||||
if FeatureFlags.enableEVCharging && needsEVCharging {
|
||||
options = await ItineraryBuilder.enrichWithEVChargers(options)
|
||||
}
|
||||
|
||||
} catch {
|
||||
viewState = .error("Trip planning failed: \(error.localizedDescription)")
|
||||
// Store preferences for later conversion
|
||||
currentPreferences = preferences
|
||||
|
||||
if options.count == 1 {
|
||||
// Only one option - go directly to detail
|
||||
let trip = convertToTrip(option: options[0], preferences: preferences)
|
||||
viewState = .completed(trip)
|
||||
} else {
|
||||
// Multiple options - show selection view
|
||||
viewState = .selectingOption(options)
|
||||
}
|
||||
|
||||
case .failure(let failure):
|
||||
viewState = .error(failureMessage(for: failure))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,9 +62,7 @@ struct TripDetailView: View {
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .primaryAction) {
|
||||
Button {
|
||||
Task {
|
||||
await shareTrip()
|
||||
}
|
||||
shareTrip()
|
||||
} label: {
|
||||
Image(systemName: "square.and.arrow.up")
|
||||
.foregroundStyle(Theme.warmOrange)
|
||||
@@ -429,8 +427,10 @@ struct TripDetailView: View {
|
||||
let destination = stops[i + 1]
|
||||
|
||||
let request = MKDirections.Request()
|
||||
request.source = MKMapItem(placemark: MKPlacemark(coordinate: source.coordinate))
|
||||
request.destination = MKMapItem(placemark: MKPlacemark(coordinate: destination.coordinate))
|
||||
let sourceLocation = CLLocation(latitude: source.coordinate.latitude, longitude: source.coordinate.longitude)
|
||||
let destLocation = CLLocation(latitude: destination.coordinate.latitude, longitude: destination.coordinate.longitude)
|
||||
request.source = MKMapItem(location: sourceLocation, address: nil)
|
||||
request.destination = MKMapItem(location: destLocation, address: nil)
|
||||
request.transportType = .automobile
|
||||
|
||||
let directions = MKDirections(request: request)
|
||||
@@ -504,14 +504,14 @@ struct TripDetailView: View {
|
||||
exportURL = url
|
||||
showExportSheet = true
|
||||
} catch {
|
||||
print("Failed to export PDF: \(error)")
|
||||
// PDF export failed silently
|
||||
}
|
||||
|
||||
isExporting = false
|
||||
}
|
||||
|
||||
private func shareTrip() async {
|
||||
shareURL = await exportService.shareTrip(trip)
|
||||
private func shareTrip() {
|
||||
shareURL = exportService.shareTrip(trip)
|
||||
showShareSheet = true
|
||||
}
|
||||
|
||||
@@ -525,7 +525,6 @@ struct TripDetailView: View {
|
||||
|
||||
private func saveTrip() {
|
||||
guard let savedTrip = SavedTrip.from(trip, games: games, status: .planned) else {
|
||||
print("Failed to create SavedTrip")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -537,7 +536,7 @@ struct TripDetailView: View {
|
||||
isSaved = true
|
||||
}
|
||||
} catch {
|
||||
print("Failed to save trip: \(error)")
|
||||
// Save failed silently
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,7 +556,7 @@ struct TripDetailView: View {
|
||||
isSaved = false
|
||||
}
|
||||
} catch {
|
||||
print("Failed to unsave trip: \(error)")
|
||||
// Unsave failed silently
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user