Skip to content

Commit

Permalink
Merge pull request #65 from OneBusAway/add-custom-region-onboarding
Browse files Browse the repository at this point in the history
Add onboarding for otpkitdemo
  • Loading branch information
aaronbrethorst authored Aug 28, 2024
2 parents c724fa5 + a36551e commit 77ff1e3
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 42 deletions.
19 changes: 7 additions & 12 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -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.)
30 changes: 30 additions & 0 deletions Examples/OTPKitDemo/OTPKitDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand All @@ -18,6 +19,7 @@

/* Begin PBXFileReference section */
014316E02C6B713D00B33240 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
0153646F2C7E93BE00146182 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = "<group>"; };
01AA23152C758E62008F484E /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
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 = "<group>"; };
Expand Down Expand Up @@ -62,6 +64,7 @@
014316E02C6B713D00B33240 /* Info.plist */,
01AA80532C6B6A7500D4038A /* OTPKitDemoApp.swift */,
01AA80552C6B6A7500D4038A /* MapView.swift */,
0153646F2C7E93BE00146182 /* OnboardingView.swift */,
01AA80572C6B6A7600D4038A /* Assets.xcassets */,
01AA80592C6B6A7600D4038A /* Preview Content */,
);
Expand All @@ -86,6 +89,7 @@
01AA804C2C6B6A7500D4038A /* Sources */,
01AA804D2C6B6A7500D4038A /* Frameworks */,
01AA804E2C6B6A7500D4038A /* Resources */,
933C43692C7EC6B600DEB5B7 /* SwiftLint */,
);
buildRules = (
);
Expand Down Expand Up @@ -149,11 +153,35 @@
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
933C43692C7EC6B600DEB5B7 /* SwiftLint */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = SwiftLint;
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [[ \"$(uname -m)\" == arm64 ]]; then\n export PATH=\"/opt/homebrew/bin:$PATH\"\nfi\n\nif which swiftlint > /dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
01AA804C2C6B6A7500D4038A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
015364702C7E93BE00146182 /* OnboardingView.swift in Sources */,
01AA80562C6B6A7500D4038A /* MapView.swift in Sources */,
01AA80542C6B6A7500D4038A /* OTPKitDemoApp.swift in Sources */,
);
Expand Down Expand Up @@ -291,6 +319,7 @@
DEVELOPMENT_ASSET_PATHS = "\"OTPKitDemo/Preview Content\"";
DEVELOPMENT_TEAM = 4ZQCMA634J;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = OTPKitDemo/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "OTPKit Demo";
Expand Down Expand Up @@ -324,6 +353,7 @@
DEVELOPMENT_ASSET_PATHS = "\"OTPKitDemo/Preview Content\"";
DEVELOPMENT_TEAM = 4ZQCMA634J;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = OTPKitDemo/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "OTPKit Demo";
Expand Down
31 changes: 14 additions & 17 deletions Examples/OTPKitDemo/OTPKitDemo/MapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
24 changes: 14 additions & 10 deletions Examples/OTPKitDemo/OTPKitDemo/OTPKitDemoApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,23 @@ 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
)
}
}
}
}
94 changes: 94 additions & 0 deletions Examples/OTPKitDemo/OTPKitDemo/OnboardingView.swift
Original file line number Diff line number Diff line change
@@ -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": URL(string: "https://otp.prod.sound.obaweb.org/otp/routers/default/")!,
"center": CLLocationCoordinate2D(latitude: 47.64585, longitude: -122.2963)
],
"San Diego": [
"url": URL(string: "https://realtime.sdmts.com:9091/otp/routers/default/")!,
"center": CLLocationCoordinate2D(latitude: 32.731591, longitude: -117.1896335)
],
"Tampa": [
"url": URL(string: "https://otp.prod.obahart.org/otp/routers/default/")!,
"center": CLLocationCoordinate2D(latitude: 27.9769105, longitude: -82.445851)
]
]

var body: some View {
VStack {
Spacer(minLength: 20)
Text("Welcome to OTPKitDemo!")
.bold()
.font(.title)

Text("Please choose your region.")

List(Array(regions.keys.sorted()), id: \.self) { key in
Button {
selectedRegion = key
} label: {
HStack {
Text(key)
Spacer()
if selectedRegion == key {
Image(systemName: "checkmark")
.foregroundColor(.blue)
}
}
}
.foregroundColor(.primary)
}

Button {
let selection = regions[selectedRegion]!

// swiftlint:disable force_cast
let url = selection["url"] as! URL
let center = selection["center"] as! CLLocationCoordinate2D
// swiftlint:enable force_cast

selectedRegionURL = url

tripPlannerService = TripPlannerService(
apiClient: RestAPI(baseURL: url),
locationManager: CLLocationManager(),
searchCompleter: MKLocalSearchCompleter()
)

tripPlannerService?.changeMapCamera(to: center)
hasCompletedOnboarding = true

} label: {
Text("OK")
.frame(maxWidth: .infinity, minHeight: 44)
}
.buttonStyle(BorderedProminentButtonStyle())
.padding()
}
.background(Color(UIColor.systemGroupedBackground))
}
}

#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)
)
}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ This project was created by Hilmy Veradin with Aaron Brethorst as part of the [G

We make extensive use of unit testing in this project to ensure that our code works as expected and our changes do not cause regressions. All PR merges are gated on unit tests passing in GitHub Actions. Please be sure to run tests locally before opening a pull request. Also, please add or update unit tests to account for changes to your code.

### Swiftlint
### SwiftLint

We make extensive use of [Swiflint](https://github.com/realm/SwiftLint) in order to ensure that our code adheres to standard styles and conventions. Please install Swiftlint locally via Homebrew:
We make extensive use of [SwiftLint](https://github.com/realm/SwiftLint) in order to ensure that our code adheres to standard styles and conventions. Please install Swiftlint locally via Homebrew:

```
brew install swiftlint
```

A clean bill of health from Swiftlint is required for merging pull requests.
A clean bill of health from SwiftLint is required for merging pull requests.

## License

Expand Down
8 changes: 8 additions & 0 deletions Sources/OTPKit/Services/TripPlannerService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand Down

0 comments on commit 77ff1e3

Please sign in to comment.