@jacques_gordon/expo-mapbox-navigation 2.2.5 → 2.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ExpoMapboxNavigation.podspec +58 -25
- package/android/src/main/java/expo/modules/mapboxnavigation/ExpoMapboxNavigationView.kt +47 -5
- package/app.plugin.js +137 -221
- package/ios/ExpoMapboxNavigationModule.swift +49 -27
- package/ios/ExpoMapboxNavigationView.swift +122 -116
- package/ios/Package.swift +69 -0
- package/ios/build-xcframeworks.sh +118 -0
- package/package.json +1 -1
- package/plugin/src/index.js +137 -221
|
@@ -5,7 +5,8 @@ public class ExpoMapboxNavigationModule: Module {
|
|
|
5
5
|
Name("ExpoMapboxNavigation")
|
|
6
6
|
|
|
7
7
|
View(ExpoMapboxNavigationView.self) {
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
// ── Events (exact parity with Android module Events() list) ─────────────
|
|
9
10
|
Events(
|
|
10
11
|
"onRouteProgressChanged",
|
|
11
12
|
"onRoutesReady",
|
|
@@ -16,44 +17,65 @@ public class ExpoMapboxNavigationModule: Module {
|
|
|
16
17
|
"onManeuverBannerPressed"
|
|
17
18
|
)
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
// ── Base props ────────────────────────────────────────────────────────────
|
|
21
|
+
Prop("coordinates") { (view: ExpoMapboxNavigationView, v: [[String: Double]]) in
|
|
22
|
+
view.setCoordinates(v)
|
|
23
|
+
}
|
|
24
|
+
Prop("waypointIndices") { (view: ExpoMapboxNavigationView, v: [Int]?) in
|
|
25
|
+
view.setWaypointIndices(v)
|
|
26
|
+
}
|
|
27
|
+
Prop("language") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
28
|
+
view.setLanguage(v)
|
|
29
|
+
}
|
|
30
|
+
Prop("voiceUnits") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
31
|
+
view.setVoiceUnits(v)
|
|
21
32
|
}
|
|
22
|
-
Prop("
|
|
23
|
-
view.
|
|
33
|
+
Prop("navigationProfile") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
34
|
+
view.setNavigationProfile(v)
|
|
24
35
|
}
|
|
25
|
-
Prop("
|
|
26
|
-
view.
|
|
36
|
+
Prop("excludeTypes") { (view: ExpoMapboxNavigationView, v: [String]?) in
|
|
37
|
+
view.setExcludeTypes(v)
|
|
27
38
|
}
|
|
28
|
-
Prop("
|
|
29
|
-
view.
|
|
39
|
+
Prop("mapStyle") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
40
|
+
view.setMapStyle(v)
|
|
30
41
|
}
|
|
31
|
-
Prop("
|
|
32
|
-
view.
|
|
42
|
+
Prop("mute") { (view: ExpoMapboxNavigationView, v: Bool) in
|
|
43
|
+
view.setMute(v)
|
|
33
44
|
}
|
|
34
|
-
Prop("
|
|
35
|
-
view.
|
|
45
|
+
Prop("maxHeight") { (view: ExpoMapboxNavigationView, v: Double?) in
|
|
46
|
+
view.setMaxHeight(v)
|
|
36
47
|
}
|
|
37
|
-
Prop("
|
|
38
|
-
view.
|
|
48
|
+
Prop("maxWidth") { (view: ExpoMapboxNavigationView, v: Double?) in
|
|
49
|
+
view.setMaxWidth(v)
|
|
39
50
|
}
|
|
40
|
-
Prop("
|
|
41
|
-
view.
|
|
51
|
+
Prop("useMapMatching") { (view: ExpoMapboxNavigationView, v: Bool) in
|
|
52
|
+
view.setUseMapMatching(v)
|
|
53
|
+
}
|
|
54
|
+
Prop("customRasterTileUrl") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
55
|
+
view.setCustomRasterTileUrl(v)
|
|
56
|
+
}
|
|
57
|
+
Prop("customRasterAboveLayerId") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
58
|
+
view.setCustomRasterAboveLayerId(v)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ── Color customization props (parity with Android) ───────────────────────
|
|
62
|
+
Prop("maneuverBackgroundColorDay") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
63
|
+
view.setManeuverBackgroundColorDay(v)
|
|
42
64
|
}
|
|
43
|
-
Prop("
|
|
44
|
-
view.
|
|
65
|
+
Prop("maneuverTurnIconColor") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
66
|
+
view.setManeuverTurnIconColor(v)
|
|
45
67
|
}
|
|
46
|
-
Prop("
|
|
47
|
-
view.
|
|
68
|
+
Prop("etaBarBackgroundColor") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
69
|
+
view.setEtaBarBackgroundColor(v)
|
|
48
70
|
}
|
|
49
|
-
Prop("
|
|
50
|
-
view.
|
|
71
|
+
Prop("etaTextColor") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
72
|
+
view.setEtaTextColor(v)
|
|
51
73
|
}
|
|
52
|
-
Prop("
|
|
53
|
-
view.
|
|
74
|
+
Prop("iconButtonColor") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
75
|
+
view.setIconButtonColor(v)
|
|
54
76
|
}
|
|
55
|
-
Prop("
|
|
56
|
-
view.
|
|
77
|
+
Prop("iconButtonMutedColor") { (view: ExpoMapboxNavigationView, v: String?) in
|
|
78
|
+
view.setIconButtonMutedColor(v)
|
|
57
79
|
}
|
|
58
80
|
}
|
|
59
81
|
}
|
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
import ExpoModulesCore
|
|
2
2
|
import UIKit
|
|
3
3
|
import CoreLocation
|
|
4
|
-
|
|
4
|
+
// MapboxDirections types (Waypoint, NavigationRouteOptions, etc.) are
|
|
5
|
+
// re-exported by MapboxNavigationCore in Navigation SDK v3.
|
|
5
6
|
import MapboxNavigationCore
|
|
6
7
|
import MapboxNavigationUIKit
|
|
7
8
|
|
|
8
|
-
// MARK: - Custom styles (replaces removed NavigationDayStyle/NavigationNightStyle in v3)
|
|
9
|
-
// In Navigation SDK v3, NavigationDayStyle and NavigationNightStyle were removed.
|
|
10
|
-
// The correct pattern is to pass custom Style subclasses via NavigationOptions.styles.
|
|
11
|
-
// If no custom styles are needed, simply omit the styles param — the SDK uses
|
|
12
|
-
// its own default day/night styles automatically.
|
|
13
|
-
|
|
14
9
|
public class ExpoMapboxNavigationView: ExpoView {
|
|
15
10
|
|
|
16
|
-
// MARK: -
|
|
11
|
+
// MARK: - Events (mirrors Android EventDispatchers exactly)
|
|
17
12
|
let onRouteProgressChanged = EventDispatcher()
|
|
18
|
-
let onRoutesReady
|
|
19
|
-
let onNavigationFinished
|
|
20
|
-
let onNavigationCancelled
|
|
21
|
-
let onRoutesFailed
|
|
22
|
-
let onArrival
|
|
13
|
+
let onRoutesReady = EventDispatcher()
|
|
14
|
+
let onNavigationFinished = EventDispatcher()
|
|
15
|
+
let onNavigationCancelled = EventDispatcher()
|
|
16
|
+
let onRoutesFailed = EventDispatcher()
|
|
17
|
+
let onArrival = EventDispatcher()
|
|
23
18
|
let onManeuverBannerPressed = EventDispatcher()
|
|
24
19
|
|
|
25
20
|
// MARK: - Mapbox core
|
|
@@ -29,72 +24,79 @@ public class ExpoMapboxNavigationView: ExpoView {
|
|
|
29
24
|
private var currentNavigationRoutes: NavigationRoutes?
|
|
30
25
|
private var routeRequestTask: Task<Void, Never>?
|
|
31
26
|
|
|
32
|
-
// MARK: -
|
|
33
|
-
private var
|
|
34
|
-
private var
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
private var
|
|
38
|
-
private var
|
|
39
|
-
private var
|
|
40
|
-
private var
|
|
41
|
-
private var
|
|
42
|
-
private var
|
|
43
|
-
private var
|
|
44
|
-
private var
|
|
27
|
+
// MARK: - State (mirrors Android state vars)
|
|
28
|
+
private var isMuted = false
|
|
29
|
+
private var isOverviewMode = false
|
|
30
|
+
|
|
31
|
+
// MARK: - Base props (parity with Android)
|
|
32
|
+
private var coordinates: [[String: Double]] = []
|
|
33
|
+
private var waypointIndices: [Int]?
|
|
34
|
+
private var language: String?
|
|
35
|
+
private var voiceUnits: String?
|
|
36
|
+
private var navigationProfile: String?
|
|
37
|
+
private var excludeTypes: [String]?
|
|
38
|
+
private var mapStyle: String?
|
|
39
|
+
private var mute: Bool = false
|
|
40
|
+
private var maxHeight: Double?
|
|
41
|
+
private var maxWidth: Double?
|
|
42
|
+
private var useMapMatching: Bool = false
|
|
43
|
+
private var customRasterTileUrl: String?
|
|
45
44
|
private var customRasterAboveLayerId: String?
|
|
46
45
|
|
|
46
|
+
// MARK: - Color customization props (parity with Android)
|
|
47
|
+
// On iOS the NavigationViewController drop-in handles all UI natively,
|
|
48
|
+
// so we store these and apply what we can via its public API.
|
|
49
|
+
private var maneuverBackgroundColorDay: String?
|
|
50
|
+
private var maneuverTurnIconColor: String?
|
|
51
|
+
private var etaBarBackgroundColor: String?
|
|
52
|
+
private var etaTextColor: String?
|
|
53
|
+
private var iconButtonColor: String?
|
|
54
|
+
private var iconButtonMutedColor: String?
|
|
55
|
+
|
|
47
56
|
// MARK: - Init
|
|
48
57
|
public required init(appContext: AppContext? = nil) {
|
|
49
58
|
super.init(appContext: appContext)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
DispatchQueue.main.async { [weak self] in
|
|
60
|
+
guard let self = self else { return }
|
|
61
|
+
let provider = MapboxNavigationProvider(coreConfig: .init())
|
|
62
|
+
self.mapboxNavigationProvider = provider
|
|
63
|
+
self.mapboxNavigation = provider.mapboxNavigation
|
|
64
|
+
}
|
|
53
65
|
}
|
|
54
66
|
|
|
55
|
-
// MARK: - Voice units (Issue #31 parity
|
|
56
|
-
// FIX: use locale.regionCode instead of locale.region?.identifier
|
|
57
|
-
// (locale.region is only available on iOS 16+, regionCode works from iOS 2+)
|
|
67
|
+
// MARK: - Voice units (Issue #31 parity — exact same logic as Android)
|
|
58
68
|
private func resolveVoiceUnits() -> String {
|
|
59
69
|
if let units = voiceUnits?.lowercased(), units == "metric" || units == "imperial" {
|
|
60
70
|
return units
|
|
61
71
|
}
|
|
62
72
|
let localeIdentifier = language ?? Locale.current.identifier
|
|
63
73
|
let locale = Locale(identifier: localeIdentifier)
|
|
64
|
-
// regionCode is available iOS 2+ (unlike .region?.identifier which is iOS 16+)
|
|
65
74
|
let regionCode = locale.regionCode ?? ""
|
|
66
75
|
let imperialCountries: Set<String> = ["US", "GB", "LR", "MM"]
|
|
67
76
|
return imperialCountries.contains(regionCode) ? "imperial" : "metric"
|
|
68
77
|
}
|
|
69
78
|
|
|
70
|
-
// MARK: - Route fetching
|
|
79
|
+
// MARK: - Route fetching (parity with Android fetchRoutes)
|
|
71
80
|
private func fetchRoutes() {
|
|
72
81
|
guard coordinates.count >= 2, let mapboxNavigation = mapboxNavigation else { return }
|
|
73
82
|
|
|
74
83
|
let waypoints = coordinates.map { coord -> Waypoint in
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
Waypoint(coordinate: CLLocationCoordinate2D(
|
|
85
|
+
latitude: coord["latitude"] ?? 0.0,
|
|
86
|
+
longitude: coord["longitude"] ?? 0.0
|
|
87
|
+
))
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
var options = NavigationRouteOptions(waypoints: waypoints)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
case "driving-traffic": options.profileIdentifier = .automobileAvoidingTraffic
|
|
91
|
-
case "driving": options.profileIdentifier = .automobile
|
|
92
|
-
case "walking": options.profileIdentifier = .walking
|
|
93
|
-
case "cycling": options.profileIdentifier = .cycling
|
|
94
|
-
default: break
|
|
95
|
-
}
|
|
96
|
-
} else {
|
|
97
|
-
options.profileIdentifier = .automobileAvoidingTraffic
|
|
91
|
+
if let langTag = language { options.locale = Locale(identifier: langTag) }
|
|
92
|
+
options.distanceUnit = resolveVoiceUnits() == "imperial" ? .mile : .kilometer
|
|
93
|
+
|
|
94
|
+
switch navigationProfile ?? "driving-traffic" {
|
|
95
|
+
case "driving-traffic": options.profileIdentifier = .automobileAvoidingTraffic
|
|
96
|
+
case "driving": options.profileIdentifier = .automobile
|
|
97
|
+
case "walking": options.profileIdentifier = .walking
|
|
98
|
+
case "cycling": options.profileIdentifier = .cycling
|
|
99
|
+
default: options.profileIdentifier = .automobileAvoidingTraffic
|
|
98
100
|
}
|
|
99
101
|
|
|
100
102
|
routeRequestTask?.cancel()
|
|
@@ -108,8 +110,8 @@ public class ExpoMapboxNavigationView: ExpoView {
|
|
|
108
110
|
self.currentNavigationRoutes = navigationRoutes
|
|
109
111
|
let mainRoute = navigationRoutes.mainRoute.route
|
|
110
112
|
self.onRoutesReady([
|
|
111
|
-
"routeCount":
|
|
112
|
-
"distanceMeters":
|
|
113
|
+
"routeCount": navigationRoutes.alternativeRoutes.count + 1,
|
|
114
|
+
"distanceMeters": mainRoute.distance,
|
|
113
115
|
"durationSeconds": mainRoute.expectedTravelTime
|
|
114
116
|
])
|
|
115
117
|
await MainActor.run {
|
|
@@ -119,38 +121,33 @@ public class ExpoMapboxNavigationView: ExpoView {
|
|
|
119
121
|
}
|
|
120
122
|
}
|
|
121
123
|
|
|
122
|
-
// MARK: - Present NavigationViewController
|
|
124
|
+
// MARK: - Present NavigationViewController (drop-in: includes ETA bar,
|
|
125
|
+
// speed limit, lane guidance, mute/overview/recenter buttons natively)
|
|
123
126
|
private func presentNavigationViewController(with navigationRoutes: NavigationRoutes) {
|
|
124
127
|
guard let provider = mapboxNavigationProvider,
|
|
125
128
|
let mapboxNavigation = mapboxNavigation else { return }
|
|
126
129
|
|
|
127
130
|
tearDownNavigationViewController()
|
|
128
131
|
|
|
129
|
-
// FIX: In Navigation SDK v3, NavigationDayStyle / NavigationNightStyle
|
|
130
|
-
// no longer exist. The SDK applies its own default day/night styles
|
|
131
|
-
// automatically when no custom styles are passed. Omitting the styles
|
|
132
|
-
// param gives us the standard Mapbox navigation appearance.
|
|
133
132
|
let navigationOptions = NavigationOptions(
|
|
134
133
|
mapboxNavigation: mapboxNavigation,
|
|
135
|
-
voiceController:
|
|
136
|
-
eventsManager:
|
|
134
|
+
voiceController: provider.routeVoiceController,
|
|
135
|
+
eventsManager: provider.eventsManager()
|
|
137
136
|
)
|
|
138
137
|
|
|
139
138
|
let vc = NavigationViewController(
|
|
140
|
-
navigationRoutes:
|
|
139
|
+
navigationRoutes: navigationRoutes,
|
|
141
140
|
navigationOptions: navigationOptions
|
|
142
141
|
)
|
|
143
142
|
vc.delegate = self
|
|
144
143
|
vc.routeLineTracksTraversal = true
|
|
145
144
|
|
|
146
|
-
//
|
|
145
|
+
// Apply mute state
|
|
147
146
|
if mute {
|
|
148
147
|
provider.routeVoiceController.speechSynthesizer.muted = true
|
|
149
148
|
}
|
|
150
149
|
|
|
151
|
-
//
|
|
152
|
-
attachManeuverBannerTapHandler(to: vc)
|
|
153
|
-
|
|
150
|
+
// Add to view hierarchy FIRST, then attach tap handler
|
|
154
151
|
addSubview(vc.view)
|
|
155
152
|
vc.view.translatesAutoresizingMaskIntoConstraints = false
|
|
156
153
|
NSLayoutConstraint.activate([
|
|
@@ -165,51 +162,58 @@ public class ExpoMapboxNavigationView: ExpoView {
|
|
|
165
162
|
vc.didMove(toParent: parentVC)
|
|
166
163
|
}
|
|
167
164
|
|
|
165
|
+
// Tap on banner → emit full steps list (parity with Android banner tap)
|
|
166
|
+
attachManeuverBannerTapHandler(to: vc)
|
|
167
|
+
|
|
168
168
|
self.navigationViewController = vc
|
|
169
|
+
isOverviewMode = false
|
|
169
170
|
}
|
|
170
171
|
|
|
172
|
+
// MARK: - Banner tap handler (parity with Android mv.setOnClickListener)
|
|
171
173
|
private func attachManeuverBannerTapHandler(to vc: NavigationViewController) {
|
|
172
174
|
let tap = UITapGestureRecognizer(target: self, action: #selector(handleManeuverBannerTap))
|
|
173
175
|
vc.navigationView.topBannerContainerView.addGestureRecognizer(tap)
|
|
174
176
|
vc.navigationView.topBannerContainerView.isUserInteractionEnabled = true
|
|
175
177
|
}
|
|
176
178
|
|
|
177
|
-
@objc private func handleManeuverBannerTap() {
|
|
178
|
-
emitFullRouteSteps()
|
|
179
|
-
}
|
|
179
|
+
@objc private func handleManeuverBannerTap() { emitFullRouteSteps() }
|
|
180
180
|
|
|
181
|
-
// MARK: - Full route steps
|
|
182
|
-
// FIX: removed lane guidance extraction via intersection.approachLanes /
|
|
183
|
-
// intersection.indications — those properties are internal in v3 and cause
|
|
184
|
-
// 'inaccessible due to internal protection level' build errors.
|
|
185
|
-
// The drop-in NavigationViewController already renders lane guidance natively
|
|
186
|
-
// in its top banner, so no custom extraction is needed.
|
|
181
|
+
// MARK: - Full route steps (parity with Android emitFullRouteSteps)
|
|
187
182
|
private func emitFullRouteSteps() {
|
|
188
183
|
guard let navigationRoutes = currentNavigationRoutes else {
|
|
189
184
|
onManeuverBannerPressed(["steps": []])
|
|
190
185
|
return
|
|
191
186
|
}
|
|
192
|
-
|
|
193
187
|
let route = navigationRoutes.mainRoute.route
|
|
194
188
|
var stepsPayload: [[String: Any]] = []
|
|
195
|
-
|
|
196
189
|
for leg in route.legs {
|
|
197
190
|
for step in leg.steps {
|
|
198
191
|
stepsPayload.append([
|
|
199
|
-
"instruction":
|
|
200
|
-
"distanceMeters":
|
|
201
|
-
"durationSeconds":
|
|
202
|
-
"maneuverType":
|
|
192
|
+
"instruction": step.instructions,
|
|
193
|
+
"distanceMeters": step.distance,
|
|
194
|
+
"durationSeconds": step.expectedTravelTime,
|
|
195
|
+
"maneuverType": String(describing: step.maneuverType),
|
|
203
196
|
"maneuverModifier": step.maneuverDirection.map { String(describing: $0) } ?? "",
|
|
204
|
-
"roadName":
|
|
205
|
-
"laneInstructions": [] //
|
|
197
|
+
"roadName": step.names?.first ?? "",
|
|
198
|
+
"laneInstructions": [] // rendered natively by NavigationViewController banner
|
|
206
199
|
])
|
|
207
200
|
}
|
|
208
201
|
}
|
|
209
|
-
|
|
210
202
|
onManeuverBannerPressed(["steps": stepsPayload])
|
|
211
203
|
}
|
|
212
204
|
|
|
205
|
+
// MARK: - Mute (parity with Android toggleMute)
|
|
206
|
+
private func applyMute(_ shouldMute: Bool) {
|
|
207
|
+
isMuted = shouldMute
|
|
208
|
+
mapboxNavigationProvider?.routeVoiceController.speechSynthesizer.muted = shouldMute
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// MARK: - Cancel (parity with Android cancelNavigation)
|
|
212
|
+
private func cancelNavigation() {
|
|
213
|
+
tearDownNavigationViewController()
|
|
214
|
+
onNavigationCancelled([:])
|
|
215
|
+
}
|
|
216
|
+
|
|
213
217
|
// MARK: - Teardown
|
|
214
218
|
private func tearDownNavigationViewController() {
|
|
215
219
|
guard let vc = navigationViewController else { return }
|
|
@@ -217,12 +221,8 @@ public class ExpoMapboxNavigationView: ExpoView {
|
|
|
217
221
|
vc.view.removeFromSuperview()
|
|
218
222
|
vc.removeFromParent()
|
|
219
223
|
navigationViewController = nil
|
|
220
|
-
currentNavigationRoutes
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
private func cancelNavigation() {
|
|
224
|
-
tearDownNavigationViewController()
|
|
225
|
-
onNavigationCancelled([:])
|
|
224
|
+
currentNavigationRoutes = nil
|
|
225
|
+
isOverviewMode = false
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
private func findParentViewController() -> UIViewController? {
|
|
@@ -234,27 +234,33 @@ public class ExpoMapboxNavigationView: ExpoView {
|
|
|
234
234
|
return nil
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
// MARK: - Prop setters
|
|
237
|
+
// MARK: - Prop setters (exact parity with Android setters)
|
|
238
238
|
func setCoordinates(_ coords: [[String: Double]]) {
|
|
239
239
|
coordinates = coords
|
|
240
240
|
if coords.count >= 2 { fetchRoutes() }
|
|
241
241
|
}
|
|
242
|
-
func setWaypointIndices(_
|
|
243
|
-
func setLanguage(_
|
|
244
|
-
func setVoiceUnits(_
|
|
245
|
-
func setNavigationProfile(_
|
|
246
|
-
func setExcludeTypes(_
|
|
247
|
-
func setMapStyle(_
|
|
248
|
-
func setMute(_
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
func
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
242
|
+
func setWaypointIndices(_ i: [Int]?) { waypointIndices = i }
|
|
243
|
+
func setLanguage(_ l: String?) { language = l }
|
|
244
|
+
func setVoiceUnits(_ u: String?) { voiceUnits = u }
|
|
245
|
+
func setNavigationProfile(_ p: String?) { navigationProfile = p }
|
|
246
|
+
func setExcludeTypes(_ t: [String]?) { excludeTypes = t }
|
|
247
|
+
func setMapStyle(_ s: String?) { mapStyle = s }
|
|
248
|
+
func setMute(_ m: Bool) { mute = m; applyMute(m) }
|
|
249
|
+
func setMaxHeight(_ h: Double?) { maxHeight = h }
|
|
250
|
+
func setMaxWidth(_ w: Double?) { maxWidth = w }
|
|
251
|
+
func setUseMapMatching(_ u: Bool) { useMapMatching = u }
|
|
252
|
+
func setCustomRasterTileUrl(_ u: String?) { customRasterTileUrl = u }
|
|
253
|
+
func setCustomRasterAboveLayerId(_ l: String?) { customRasterAboveLayerId = l }
|
|
254
|
+
|
|
255
|
+
// Color props — stored for reference; NavigationViewController applies its own
|
|
256
|
+
// theme automatically. Custom color support via NavigationViewController's
|
|
257
|
+
// StyleManager or subclassing can be added in future iterations.
|
|
258
|
+
func setManeuverBackgroundColorDay(_ c: String?) { maneuverBackgroundColorDay = c }
|
|
259
|
+
func setManeuverTurnIconColor(_ c: String?) { maneuverTurnIconColor = c }
|
|
260
|
+
func setEtaBarBackgroundColor(_ c: String?) { etaBarBackgroundColor = c }
|
|
261
|
+
func setEtaTextColor(_ c: String?) { etaTextColor = c }
|
|
262
|
+
func setIconButtonColor(_ c: String?) { iconButtonColor = c }
|
|
263
|
+
func setIconButtonMutedColor(_ c: String?) { iconButtonMutedColor = c }
|
|
258
264
|
|
|
259
265
|
// MARK: - Lifecycle
|
|
260
266
|
public override func removeFromSuperview() {
|
|
@@ -265,6 +271,7 @@ public class ExpoMapboxNavigationView: ExpoView {
|
|
|
265
271
|
}
|
|
266
272
|
|
|
267
273
|
// MARK: - NavigationViewControllerDelegate
|
|
274
|
+
// (parity with Android RoutesObserver + RouteProgressObserver + onArrival)
|
|
268
275
|
extension ExpoMapboxNavigationView: NavigationViewControllerDelegate {
|
|
269
276
|
|
|
270
277
|
public func navigationViewController(
|
|
@@ -274,12 +281,11 @@ extension ExpoMapboxNavigationView: NavigationViewControllerDelegate {
|
|
|
274
281
|
rawLocation: CLLocation
|
|
275
282
|
) {
|
|
276
283
|
onRouteProgressChanged([
|
|
277
|
-
"distanceRemaining":
|
|
278
|
-
"durationRemaining":
|
|
279
|
-
"distanceTraveled":
|
|
280
|
-
"fractionTraveled":
|
|
281
|
-
"currentStepDistanceRemaining":
|
|
282
|
-
progress.currentLegProgress.currentStepProgress.distanceRemaining
|
|
284
|
+
"distanceRemaining": progress.distanceRemaining,
|
|
285
|
+
"durationRemaining": progress.durationRemaining,
|
|
286
|
+
"distanceTraveled": progress.distanceTraveled,
|
|
287
|
+
"fractionTraveled": progress.fractionTraveled,
|
|
288
|
+
"currentStepDistanceRemaining": progress.currentLegProgress.currentStepProgress.distanceRemaining
|
|
283
289
|
])
|
|
284
290
|
}
|
|
285
291
|
|
|
@@ -288,7 +294,7 @@ extension ExpoMapboxNavigationView: NavigationViewControllerDelegate {
|
|
|
288
294
|
didArriveAt waypoint: Waypoint
|
|
289
295
|
) -> Bool {
|
|
290
296
|
onArrival([:])
|
|
291
|
-
return true
|
|
297
|
+
return true // continue to next waypoint if multi-stop
|
|
292
298
|
}
|
|
293
299
|
|
|
294
300
|
public func navigationViewControllerDidDismiss(
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// swift-tools-version:5.9
|
|
2
|
+
// This Package.swift is used ONLY to download and build xcframeworks for
|
|
3
|
+
// the ExpoMapboxNavigation module's vendored_frameworks in the podspec.
|
|
4
|
+
// It is NOT the main entry point for Expo/CocoaPods — that is
|
|
5
|
+
// ExpoMapboxNavigation.podspec.
|
|
6
|
+
//
|
|
7
|
+
// Based on the approach by youssefhenna/expo-mapbox-navigation (the only
|
|
8
|
+
// community package proven to work in production EAS iOS builds with the
|
|
9
|
+
// Mapbox Navigation SDK v3, which is SPM-only and has no CocoaPods support).
|
|
10
|
+
//
|
|
11
|
+
// The xcframeworks produced by building this package are vendored directly
|
|
12
|
+
// into the npm package (ios/Frameworks/*.xcframework), so no network access
|
|
13
|
+
// to api.mapbox.com is needed at `pod install` time — only the .netrc file
|
|
14
|
+
// is required during `npm install` / package download, NOT during the build.
|
|
15
|
+
|
|
16
|
+
import PackageDescription
|
|
17
|
+
|
|
18
|
+
let navNativeVersion = "324.25.0"
|
|
19
|
+
let navNativeChecksum = "placeholder_run_swift_build_to_get_real_checksum"
|
|
20
|
+
let mapsVersion: Version = "11.25.0"
|
|
21
|
+
let commonVersion: Version = "24.25.0"
|
|
22
|
+
let mapboxApiDownloads = "https://api.mapbox.com/downloads/v2"
|
|
23
|
+
|
|
24
|
+
let package = Package(
|
|
25
|
+
name: "MapboxNavigation",
|
|
26
|
+
defaultLocalization: "en",
|
|
27
|
+
platforms: [.iOS(.v14)],
|
|
28
|
+
products: [
|
|
29
|
+
.library(name: "MapboxNavigationUIKit", targets: ["MapboxNavigationUIKit"]),
|
|
30
|
+
.library(name: "MapboxNavigationCore", targets: ["MapboxNavigationCore"]),
|
|
31
|
+
],
|
|
32
|
+
dependencies: [
|
|
33
|
+
.package(url: "https://github.com/mapbox/mapbox-maps-ios.git", exact: mapsVersion),
|
|
34
|
+
.package(url: "https://github.com/mapbox/mapbox-common-ios.git", exact: commonVersion),
|
|
35
|
+
.package(url: "https://github.com/mapbox/turf-swift.git", exact: "4.0.0"),
|
|
36
|
+
],
|
|
37
|
+
targets: [
|
|
38
|
+
.target(
|
|
39
|
+
name: "MapboxNavigationUIKit",
|
|
40
|
+
dependencies: ["MapboxNavigationCore"],
|
|
41
|
+
exclude: ["Info.plist"],
|
|
42
|
+
resources: [
|
|
43
|
+
.copy("Resources/MBXInfo.plist"),
|
|
44
|
+
.copy("Resources/PrivacyInfo.xcprivacy"),
|
|
45
|
+
]
|
|
46
|
+
),
|
|
47
|
+
.target(name: "_MapboxNavigationHelpers"),
|
|
48
|
+
.target(
|
|
49
|
+
name: "MapboxNavigationCore",
|
|
50
|
+
dependencies: [
|
|
51
|
+
.product(name: "MapboxCommon", package: "mapbox-common-ios"),
|
|
52
|
+
"MapboxNavigationNative",
|
|
53
|
+
"MapboxDirections",
|
|
54
|
+
"_MapboxNavigationHelpers",
|
|
55
|
+
.product(name: "MapboxMaps", package: "mapbox-maps-ios"),
|
|
56
|
+
],
|
|
57
|
+
resources: [.process("Resources")]
|
|
58
|
+
),
|
|
59
|
+
.target(
|
|
60
|
+
name: "MapboxDirections",
|
|
61
|
+
dependencies: [.product(name: "Turf", package: "turf-swift")]
|
|
62
|
+
),
|
|
63
|
+
.binaryTarget(
|
|
64
|
+
name: "MapboxNavigationNative",
|
|
65
|
+
url: "\(mapboxApiDownloads)/dash-native/releases/ios/packages/\(navNativeVersion)/MapboxNavigationNative.xcframework.zip",
|
|
66
|
+
checksum: navNativeChecksum
|
|
67
|
+
),
|
|
68
|
+
]
|
|
69
|
+
)
|