diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 6e72ff5..7a40d4a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,22 +1,17 @@ ## Description - -Please include a summary of the changes and the related issue. Please also include relevant motivation and context. +(Please include a summary of the changes and the related issue. Please also include relevant motivation and context.) ## Related Issues - -Mention your issue by typing the issue number: #(issue number) +(Mention your issue by typing the issue number: #(issue number)) ## Media - -Please include the media if applicable. For UI changes, it is recommended to provide screen record or screenshots +(Please include the media if applicable. For UI changes, it is recommended to provide screen record or screenshots) ## Test Instructions +(Please describe the tests that you ran to verify your changes. Provide instructions so others can reproduce.) -Please describe the tests that you ran to verify your changes. Provide instructions so others can reproduce. - -1. Test A -2. Test B +1. (Test A) +2. (Test B) ## Additional Context - -Add any other context about the pull request here. +(Add any other context about the pull request here.) diff --git a/Examples/OTPKitDemo/OTPKitDemo.xcodeproj/project.pbxproj b/Examples/OTPKitDemo/OTPKitDemo.xcodeproj/project.pbxproj index 134150f..cd1486f 100644 --- a/Examples/OTPKitDemo/OTPKitDemo.xcodeproj/project.pbxproj +++ b/Examples/OTPKitDemo/OTPKitDemo.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 0111FD712C6CFBE400B4472E /* OTPKit in Frameworks */ = {isa = PBXBuildFile; productRef = 0111FD702C6CFBE400B4472E /* OTPKit */; }; 014316DF2C6B6F2C00B33240 /* OTPKit in Frameworks */ = {isa = PBXBuildFile; productRef = 014316DE2C6B6F2C00B33240 /* OTPKit */; }; + 015364702C7E93BE00146182 /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0153646F2C7E93BE00146182 /* OnboardingView.swift */; }; 01AA23162C758E62008F484E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 01AA23152C758E62008F484E /* LaunchScreen.storyboard */; }; 01AA80542C6B6A7500D4038A /* OTPKitDemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01AA80532C6B6A7500D4038A /* OTPKitDemoApp.swift */; }; 01AA80562C6B6A7500D4038A /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01AA80552C6B6A7500D4038A /* MapView.swift */; }; @@ -18,6 +19,7 @@ /* Begin PBXFileReference section */ 014316E02C6B713D00B33240 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 0153646F2C7E93BE00146182 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = ""; }; 01AA23152C758E62008F484E /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 01AA80502C6B6A7500D4038A /* OTPKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OTPKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 01AA80532C6B6A7500D4038A /* OTPKitDemoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OTPKitDemoApp.swift; sourceTree = ""; }; @@ -62,6 +64,7 @@ 014316E02C6B713D00B33240 /* Info.plist */, 01AA80532C6B6A7500D4038A /* OTPKitDemoApp.swift */, 01AA80552C6B6A7500D4038A /* MapView.swift */, + 0153646F2C7E93BE00146182 /* OnboardingView.swift */, 01AA80572C6B6A7600D4038A /* Assets.xcassets */, 01AA80592C6B6A7600D4038A /* Preview Content */, ); @@ -154,6 +157,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 015364702C7E93BE00146182 /* OnboardingView.swift in Sources */, 01AA80562C6B6A7500D4038A /* MapView.swift in Sources */, 01AA80542C6B6A7500D4038A /* OTPKitDemoApp.swift in Sources */, ); diff --git a/Examples/OTPKitDemo/OTPKitDemo/MapView.swift b/Examples/OTPKitDemo/OTPKitDemo/MapView.swift index 76acd03..b9dcb40 100644 --- a/Examples/OTPKitDemo/OTPKitDemo/MapView.swift +++ b/Examples/OTPKitDemo/OTPKitDemo/MapView.swift @@ -13,28 +13,25 @@ struct MapView: View { @Environment(TripPlannerService.self) private var tripPlanner var body: some View { - TripPlannerExtensionView { - Map(position: tripPlanner.currentCameraPositionBinding, interactionModes: .all) { - tripPlanner.generateMarkers() - tripPlanner.generateMapPolyline() - .stroke(.blue, lineWidth: 5) - } - .mapControls { - if !tripPlanner.isMapMarkingMode { - MapUserLocationButton() - MapPitchToggle() + ZStack { + TripPlannerExtensionView { + Map(position: tripPlanner.currentCameraPositionBinding, interactionModes: .all) { + tripPlanner.generateMarkers() + tripPlanner.generateMapPolyline() + .stroke(.blue, lineWidth: 5) + } + .mapControls { + if !tripPlanner.isMapMarkingMode { + MapUserLocationButton() + MapPitchToggle() + } } } } + } } #Preview { - let planner = TripPlannerService( - apiClient: RestAPI(baseURL: URL(string: "https://otp.prod.sound.obaweb.org/otp/routers/default/")!), - locationManager: CLLocationManager(), - searchCompleter: MKLocalSearchCompleter() - ) - - return MapView() + MapView() } diff --git a/Examples/OTPKitDemo/OTPKitDemo/OTPKitDemoApp.swift b/Examples/OTPKitDemo/OTPKitDemo/OTPKitDemoApp.swift index 4b49c7a..75a556b 100644 --- a/Examples/OTPKitDemo/OTPKitDemo/OTPKitDemoApp.swift +++ b/Examples/OTPKitDemo/OTPKitDemo/OTPKitDemoApp.swift @@ -21,19 +21,20 @@ import SwiftUI @main struct OTPKitDemoApp: App { - let tripPlannerService = TripPlannerService( - apiClient: RestAPI(baseURL: URL(string: "https://otp.prod.sound.obaweb.org/otp/routers/default/")!), - locationManager: CLLocationManager(), - searchCompleter: MKLocalSearchCompleter() - ) - - let sheetEnvironment = OriginDestinationSheetEnvironment() - + @State private var hasCompletedOnboarding = false + @State private var selectedRegionURL: URL? + @State private var tripPlannerService: TripPlannerService? + var body: some Scene { WindowGroup { - MapView() - .environment(tripPlannerService) - .environment(sheetEnvironment) + if hasCompletedOnboarding, let service = tripPlannerService { + MapView() + .environment(service) + .environment(OriginDestinationSheetEnvironment()) + } else { + OnboardingView(hasCompletedOnboarding: $hasCompletedOnboarding, selectedRegionURL: $selectedRegionURL, tripPlannerService: $tripPlannerService) + } } } } + diff --git a/Examples/OTPKitDemo/OTPKitDemo/OnboardingView.swift b/Examples/OTPKitDemo/OTPKitDemo/OnboardingView.swift new file mode 100644 index 0000000..87a2993 --- /dev/null +++ b/Examples/OTPKitDemo/OTPKitDemo/OnboardingView.swift @@ -0,0 +1,94 @@ +import SwiftUI +import OTPKit +import MapKit + +/// View to select region for demo purposes +struct OnboardingView: View { + @Binding var hasCompletedOnboarding: Bool + @Binding var selectedRegionURL: URL? + @Binding var tripPlannerService: TripPlannerService? + @State private var selectedRegion: String = "Puget Sound" + + private let regions = [ + "Puget Sound": [ + "url": "https://otp.prod.sound.obaweb.org/otp/routers/default/", + "lat": 47.64585, + "lon": -122.2963 + ], + "San Diego": [ + "url": "https://realtime.sdmts.com:9091/otp/routers/default/", + "lat": 32.731591, + "lon": -117.1896335 + ], + "Tampa": [ + "url": "https://otp.prod.obahart.org/otp/routers/default/", + "lat": 27.9769105, + "lon": -82.445851 + ] + ] + + var body: some View { + VStack(spacing: 20) { + Text("Hello! Welcome to OTPKitDemo!") + .font(.title) + + Text("Please choose your initial region.") + .font(.subheadline) + + List(Array(regions.keys), id: \.self) { key in + Button(action: { + selectedRegion = key + }) { + HStack { + Text(key) + Spacer() + if selectedRegion == key { + Image(systemName: "checkmark") + .foregroundColor(.blue) + } + } + } + .foregroundColor(.primary) + } + .frame(height: 200) + + Button(action: { + if let urlString = regions[selectedRegion]?["url"] as? String, + let url = URL(string: urlString), + let latitude = regions[selectedRegion]?["lat"] as? Double, + let longitude = regions[selectedRegion]?["lon"] as? Double { + + selectedRegionURL = url + + print(urlString) + tripPlannerService = TripPlannerService( + apiClient: RestAPI(baseURL: url), + locationManager: CLLocationManager(), + searchCompleter: MKLocalSearchCompleter() + ) + + let locationCoordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) + tripPlannerService?.changeMapCamera(to: locationCoordinate) + hasCompletedOnboarding = true + } + }) { + Text("Submit") + .padding() + .background(Color.blue) + .foregroundColor(.white) + .cornerRadius(10) + } + } + .padding() + } +} + +#Preview { + let planner = TripPlannerService( + apiClient: RestAPI(baseURL: URL(string: "https://otp.prod.sound.obaweb.org/otp/routers/default/")!), + locationManager: CLLocationManager(), + searchCompleter: MKLocalSearchCompleter() + ) + + return OnboardingView(hasCompletedOnboarding: .constant(true), selectedRegionURL: .constant(nil), tripPlannerService: .constant(planner)) +} diff --git a/Sources/OTPKit/Services/TripPlannerService.swift b/Sources/OTPKit/Services/TripPlannerService.swift index 5b1eff4..bf5dfa4 100644 --- a/Sources/OTPKit/Services/TripPlannerService.swift +++ b/Sources/OTPKit/Services/TripPlannerService.swift @@ -194,6 +194,14 @@ public final class TripPlannerService: NSObject { public func changeMapCamera(_ item: MKMapItem) { currentCameraPosition = MapCameraPosition.item(item) } + + /// Changes the map camera to focus on the given coordinate + /// + /// - Parameter to coordinate: Add the CLLocationCoordinate2D object + public func changeMapCamera(to coordinate: CLLocationCoordinate2D) { + let region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000) + currentCameraPosition = .region(region) + } /// Generates markers for the map based on selected points ///