@jacques_gordon/expo-mapbox-navigation 1.0.8 → 2.0.2
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 +39 -0
- package/LICENSE +21 -0
- package/README.md +103 -209
- package/android/build.gradle +101 -39
- package/android/src/main/java/expo/modules/mapboxnavigation/ExpoMapboxNavigationModule.kt +81 -77
- package/android/src/main/java/expo/modules/mapboxnavigation/ExpoMapboxNavigationView.kt +260 -142
- package/app.plugin.js +216 -1
- package/build/index.d.ts +121 -2
- package/build/index.js +34 -3
- package/build/src/index.d.ts +121 -0
- package/build/src/index.js +39 -0
- package/expo-module.config.json +1 -1
- package/package.json +38 -37
- package/plugin/src/index.js +216 -0
- package/src/index.tsx +162 -0
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
- package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.2.0/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/build/MapboxNavigation.types.d.ts +0 -132
- package/build/MapboxNavigation.types.js +0 -2
- package/build/MapboxNavigationView.d.ts +0 -30
- package/build/MapboxNavigationView.js +0 -41
- package/ios/ExpoMapboxNavigation.podspec +0 -25
- package/ios/ExpoMapboxNavigationModule.swift +0 -81
- package/ios/ExpoMapboxNavigationView.swift +0 -236
- package/plugin/index.js +0 -167
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import ExpoModulesCore
|
|
2
|
-
|
|
3
|
-
public class ExpoMapboxNavigationModule: Module {
|
|
4
|
-
public func definition() -> ModuleDefinition {
|
|
5
|
-
Name("ExpoMapboxNavigation")
|
|
6
|
-
|
|
7
|
-
View(ExpoMapboxNavigationView.self) {
|
|
8
|
-
|
|
9
|
-
// ─── Props ────────────────────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
Prop("coordinates") { (view: ExpoMapboxNavigationView, value: [[String: Double]]) in
|
|
12
|
-
view.coordinates = value
|
|
13
|
-
view.startNavigationIfReady()
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
Prop("waypointIndices") { (view: ExpoMapboxNavigationView, value: [Int]) in
|
|
17
|
-
view.waypointIndices = value
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
Prop("useRouteMatchingApi") { (view: ExpoMapboxNavigationView, value: Bool) in
|
|
21
|
-
view.useRouteMatchingApi = value
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
Prop("locale") { (view: ExpoMapboxNavigationView, value: String) in
|
|
25
|
-
view.locale = value
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
Prop("routeProfile") { (view: ExpoMapboxNavigationView, value: String) in
|
|
29
|
-
view.routeProfile = value
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
Prop("routeExcludeList") { (view: ExpoMapboxNavigationView, value: [String]) in
|
|
33
|
-
view.routeExcludeList = value
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
Prop("mapStyle") { (view: ExpoMapboxNavigationView, value: String) in
|
|
37
|
-
view.mapStyle = value
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
Prop("mute") { (view: ExpoMapboxNavigationView, value: Bool) in
|
|
41
|
-
view.mute = value
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
Prop("vehicleMaxHeight") { (view: ExpoMapboxNavigationView, value: Double) in
|
|
45
|
-
view.vehicleMaxHeight = value
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
Prop("vehicleMaxWidth") { (view: ExpoMapboxNavigationView, value: Double) in
|
|
49
|
-
view.vehicleMaxWidth = value
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
Prop("customRasterSourceUrl") { (view: ExpoMapboxNavigationView, value: String) in
|
|
53
|
-
view.customRasterSourceUrl = value
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
Prop("placeCustomRasterLayerAbove") { (view: ExpoMapboxNavigationView, value: String) in
|
|
57
|
-
view.placeCustomRasterLayerAbove = value
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
Prop("disableAlternativeRoutes") { (view: ExpoMapboxNavigationView, value: Bool) in
|
|
61
|
-
view.disableAlternativeRoutes = value
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
Prop("showsEndOfRouteFeedback") { (view: ExpoMapboxNavigationView, value: Bool) in
|
|
65
|
-
view.showsEndOfRouteFeedback = value
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// ─── Events ───────────────────────────────────────────────────────
|
|
69
|
-
|
|
70
|
-
Events(
|
|
71
|
-
"onRouteProgressChanged",
|
|
72
|
-
"onWaypointArrival",
|
|
73
|
-
"onFinalDestinationArrival",
|
|
74
|
-
"onCancelNavigation",
|
|
75
|
-
"onRouteChanged",
|
|
76
|
-
"onUserOffRoute",
|
|
77
|
-
"onRoutesLoaded"
|
|
78
|
-
)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import ExpoModulesCore
|
|
2
|
-
import MapboxNavigationCore
|
|
3
|
-
import MapboxNavigationUIKit
|
|
4
|
-
import MapboxMaps
|
|
5
|
-
import MapboxDirections
|
|
6
|
-
|
|
7
|
-
class ExpoMapboxNavigationView: ExpoView {
|
|
8
|
-
|
|
9
|
-
// ─── Props ──────────────────────────────────────────────────────────────
|
|
10
|
-
var coordinates: [[String: Double]] = []
|
|
11
|
-
var waypointIndices: [Int] = []
|
|
12
|
-
var useRouteMatchingApi: Bool = false
|
|
13
|
-
var locale: String = ""
|
|
14
|
-
var routeProfile: String = "mapbox/driving-traffic"
|
|
15
|
-
var routeExcludeList: [String] = []
|
|
16
|
-
var mapStyle: String? = nil
|
|
17
|
-
var mute: Bool = false
|
|
18
|
-
var vehicleMaxHeight: Double? = nil
|
|
19
|
-
var vehicleMaxWidth: Double? = nil
|
|
20
|
-
var customRasterSourceUrl: String? = nil
|
|
21
|
-
var placeCustomRasterLayerAbove: String? = nil
|
|
22
|
-
var disableAlternativeRoutes: Bool = false
|
|
23
|
-
var showsEndOfRouteFeedback: Bool = false
|
|
24
|
-
|
|
25
|
-
// ─── Events ─────────────────────────────────────────────────────────────
|
|
26
|
-
let onRouteProgressChanged = EventDispatcher()
|
|
27
|
-
let onWaypointArrival = EventDispatcher()
|
|
28
|
-
let onFinalDestinationArrival = EventDispatcher()
|
|
29
|
-
let onCancelNavigation = EventDispatcher()
|
|
30
|
-
let onRouteChanged = EventDispatcher()
|
|
31
|
-
let onUserOffRoute = EventDispatcher()
|
|
32
|
-
let onRoutesLoaded = EventDispatcher()
|
|
33
|
-
|
|
34
|
-
// ─── Internal ───────────────────────────────────────────────────────────
|
|
35
|
-
private var navigationViewController: NavigationViewController?
|
|
36
|
-
private var isNavigationStarted = false
|
|
37
|
-
private var currentWaypointIndex = 0
|
|
38
|
-
private var totalWaypoints = 0
|
|
39
|
-
|
|
40
|
-
required init(appContext: AppContext? = nil) {
|
|
41
|
-
super.init(appContext: appContext)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
func startNavigationIfReady() {
|
|
45
|
-
guard coordinates.count >= 2, !isNavigationStarted else { return }
|
|
46
|
-
isNavigationStarted = true
|
|
47
|
-
setupNavigation()
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
override func layoutSubviews() {
|
|
51
|
-
super.layoutSubviews()
|
|
52
|
-
startNavigationIfReady()
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// ─── Navigation Setup ───────────────────────────────────────────────────
|
|
56
|
-
|
|
57
|
-
private func setupNavigation() {
|
|
58
|
-
// Construire les waypoints
|
|
59
|
-
var allWaypoints: [Waypoint] = []
|
|
60
|
-
|
|
61
|
-
for (index, coord) in coordinates.enumerated() {
|
|
62
|
-
guard let lat = coord["latitude"], let lng = coord["longitude"] else { continue }
|
|
63
|
-
let location = CLLocationCoordinate2D(latitude: lat, longitude: lng)
|
|
64
|
-
let wp = Waypoint(coordinate: location)
|
|
65
|
-
|
|
66
|
-
// Marquer les waypoints intermédiaires vs simples pass-through
|
|
67
|
-
if !waypointIndices.isEmpty {
|
|
68
|
-
wp.separatesLegs = waypointIndices.contains(index)
|
|
69
|
-
} else {
|
|
70
|
-
wp.separatesLegs = true
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
allWaypoints.append(wp)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
totalWaypoints = allWaypoints.filter { $0.separatesLegs }.count
|
|
77
|
-
|
|
78
|
-
// Choisir le profil de routing
|
|
79
|
-
let profile: ProfileIdentifier
|
|
80
|
-
switch routeProfile {
|
|
81
|
-
case "mapbox/driving": profile = .automobile
|
|
82
|
-
case "mapbox/walking": profile = .walking
|
|
83
|
-
case "mapbox/cycling": profile = .cycling
|
|
84
|
-
default: profile = .automobileAvoidingTraffic
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Options de route
|
|
88
|
-
let routeOptions = NavigationRouteOptions(waypoints: allWaypoints, profileIdentifier: profile)
|
|
89
|
-
|
|
90
|
-
let resolvedLocale = locale.isEmpty ? Locale.current.identifier : locale
|
|
91
|
-
routeOptions.locale = Locale(identifier: resolvedLocale)
|
|
92
|
-
routeOptions.includesSpokenInstructions = true
|
|
93
|
-
routeOptions.includesVisualInstructions = true
|
|
94
|
-
|
|
95
|
-
// Exclusions
|
|
96
|
-
if !routeExcludeList.isEmpty {
|
|
97
|
-
routeOptions.roadClassesToAvoid = buildRoadClassesToAvoid(routeExcludeList)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Restrictions de véhicule
|
|
101
|
-
if let maxH = vehicleMaxHeight {
|
|
102
|
-
routeOptions.maximumHeight = Measurement(value: maxH, unit: .meters)
|
|
103
|
-
}
|
|
104
|
-
if let maxW = vehicleMaxWidth {
|
|
105
|
-
routeOptions.maximumWidth = Measurement(value: maxW, unit: .meters)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if disableAlternativeRoutes {
|
|
109
|
-
routeOptions.includesAlternativeRoutes = false
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Calcul de la route
|
|
113
|
-
Directions.shared.calculate(routeOptions) { [weak self] (_, result) in
|
|
114
|
-
guard let self = self else { return }
|
|
115
|
-
switch result {
|
|
116
|
-
case .failure(let error):
|
|
117
|
-
print("[ExpoMapboxNavigation] Erreur calcul route: \(error.localizedDescription)")
|
|
118
|
-
case .success(let response):
|
|
119
|
-
guard let routes = response.routes, !routes.isEmpty else { return }
|
|
120
|
-
self.onRoutesLoaded([:])
|
|
121
|
-
self.presentNavigationUI(routes: routes, options: routeOptions)
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
private func presentNavigationUI(routes: [Route], options: NavigationRouteOptions) {
|
|
127
|
-
DispatchQueue.main.async { [weak self] in
|
|
128
|
-
guard let self = self else { return }
|
|
129
|
-
|
|
130
|
-
let navigationService = MapboxNavigationService(
|
|
131
|
-
routes: routes,
|
|
132
|
-
customRoutingProvider: NavigationSettings.shared.directions,
|
|
133
|
-
credentials: NavigationSettings.shared.directions.credentials,
|
|
134
|
-
simulating: .onPoorGPS
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
let navigationOptions = NavigationOptions(navigationService: navigationService)
|
|
138
|
-
let navVC = NavigationViewController(
|
|
139
|
-
for: routes,
|
|
140
|
-
routeIndex: 0,
|
|
141
|
-
routeOptions: options,
|
|
142
|
-
navigationOptions: navigationOptions
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
navVC.delegate = self
|
|
146
|
-
navVC.showsEndOfRouteFeedback = self.showsEndOfRouteFeedback
|
|
147
|
-
navVC.showsReportFeedback = false
|
|
148
|
-
|
|
149
|
-
if self.mute {
|
|
150
|
-
navVC.navigationService.router.reroutesProactively = false
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
self.navigationViewController = navVC
|
|
154
|
-
|
|
155
|
-
guard let parentVC = self.parentViewController else { return }
|
|
156
|
-
parentVC.addChild(navVC)
|
|
157
|
-
navVC.view.frame = self.bounds
|
|
158
|
-
navVC.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
159
|
-
self.addSubview(navVC.view)
|
|
160
|
-
navVC.didMove(toParent: parentVC)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
private func buildRoadClassesToAvoid(_ list: [String]) -> RoadClasses {
|
|
165
|
-
var classes = RoadClasses()
|
|
166
|
-
for item in list {
|
|
167
|
-
switch item {
|
|
168
|
-
case "toll": classes.insert(.toll)
|
|
169
|
-
case "ferry": classes.insert(.ferry)
|
|
170
|
-
case "motorway": classes.insert(.motorway)
|
|
171
|
-
default: break
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return classes
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
private var parentViewController: UIViewController? {
|
|
178
|
-
var responder: UIResponder? = self
|
|
179
|
-
while let r = responder {
|
|
180
|
-
if let vc = r as? UIViewController { return vc }
|
|
181
|
-
responder = r.next
|
|
182
|
-
}
|
|
183
|
-
return nil
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// ─── NavigationViewControllerDelegate ───────────────────────────────────────
|
|
188
|
-
|
|
189
|
-
extension ExpoMapboxNavigationView: NavigationViewControllerDelegate {
|
|
190
|
-
|
|
191
|
-
func navigationViewController(
|
|
192
|
-
_ vc: NavigationViewController,
|
|
193
|
-
didUpdate progress: RouteProgress,
|
|
194
|
-
with location: CLLocation,
|
|
195
|
-
rawLocation: CLLocation
|
|
196
|
-
) {
|
|
197
|
-
onRouteProgressChanged([
|
|
198
|
-
"distanceRemaining": progress.currentLegProgress.distanceRemaining,
|
|
199
|
-
"distanceTraveled": progress.distanceTraveled,
|
|
200
|
-
"durationRemaining": progress.durationRemaining,
|
|
201
|
-
"fractionTraveled": progress.fractionTraveled
|
|
202
|
-
])
|
|
203
|
-
|
|
204
|
-
// Détection hors route
|
|
205
|
-
if progress.currentLegProgress.userHasArrivedAtWaypoint {
|
|
206
|
-
currentWaypointIndex += 1
|
|
207
|
-
if currentWaypointIndex < totalWaypoints - 1 {
|
|
208
|
-
onWaypointArrival([
|
|
209
|
-
"distanceRemaining": progress.currentLegProgress.distanceRemaining,
|
|
210
|
-
"distanceTraveled": progress.distanceTraveled,
|
|
211
|
-
"durationRemaining": progress.durationRemaining,
|
|
212
|
-
"fractionTraveled": progress.fractionTraveled
|
|
213
|
-
])
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
func navigationViewControllerDidFinishRouting(_ vc: NavigationViewController) {
|
|
219
|
-
onFinalDestinationArrival([:])
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
func navigationViewControllerDidDismiss(_ vc: NavigationViewController, byCanceling canceled: Bool) {
|
|
223
|
-
if canceled {
|
|
224
|
-
onCancelNavigation([:])
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
func navigationViewController(_ vc: NavigationViewController, didRerouteAlong route: Route) {
|
|
229
|
-
onRouteChanged([:])
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
func navigationViewController(_ vc: NavigationViewController, shouldRerouteFrom location: CLLocation) -> Bool {
|
|
233
|
-
onUserOffRoute([:])
|
|
234
|
-
return true
|
|
235
|
-
}
|
|
236
|
-
}
|
package/plugin/index.js
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
const {
|
|
2
|
-
withInfoPlist,
|
|
3
|
-
withAppBuildGradle,
|
|
4
|
-
withProjectBuildGradle,
|
|
5
|
-
withAndroidManifest,
|
|
6
|
-
withDangerousMod,
|
|
7
|
-
createRunOncePlugin,
|
|
8
|
-
} = require('@expo/config-plugins');
|
|
9
|
-
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
|
|
13
|
-
// ─── Mapbox Maven block ────────────────────────────────────────────────
|
|
14
|
-
|
|
15
|
-
const MAPBOX_MAVEN_BLOCK = `
|
|
16
|
-
maven {
|
|
17
|
-
url 'https://api.mapbox.com/downloads/v2/releases/maven'
|
|
18
|
-
authentication { basic(BasicAuthentication) }
|
|
19
|
-
credentials {
|
|
20
|
-
username = "mapbox"
|
|
21
|
-
password = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: System.getenv("MAPBOX_DOWNLOADS_TOKEN") ?: ""
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
`;
|
|
25
|
-
|
|
26
|
-
// ─── Inject into settings.gradle (SDK 53 FIX) ───────────────────────────
|
|
27
|
-
|
|
28
|
-
const withMapboxMavenInSettings = (config) => {
|
|
29
|
-
return withDangerousMod(config, [
|
|
30
|
-
'android',
|
|
31
|
-
async (cfg) => {
|
|
32
|
-
const settingsPath = path.join(
|
|
33
|
-
cfg.modRequest.platformProjectRoot,
|
|
34
|
-
'settings.gradle'
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
if (!fs.existsSync(settingsPath)) return cfg;
|
|
38
|
-
|
|
39
|
-
let contents = fs.readFileSync(settingsPath, 'utf8');
|
|
40
|
-
|
|
41
|
-
if (contents.includes('api.mapbox.com/downloads')) return cfg;
|
|
42
|
-
|
|
43
|
-
if (contents.includes('dependencyResolutionManagement')) {
|
|
44
|
-
contents = contents.replace(
|
|
45
|
-
/dependencyResolutionManagement\s*\{([\s\S]*?)repositories\s*\{/,
|
|
46
|
-
`dependencyResolutionManagement {$1repositories {${MAPBOX_MAVEN_BLOCK}`
|
|
47
|
-
);
|
|
48
|
-
} else if (contents.includes('allprojects')) {
|
|
49
|
-
contents = contents.replace(
|
|
50
|
-
/allprojects\s*\{([\s\S]*?)repositories\s*\{/,
|
|
51
|
-
`allprojects {$1repositories {${MAPBOX_MAVEN_BLOCK}`
|
|
52
|
-
);
|
|
53
|
-
} else {
|
|
54
|
-
contents += `
|
|
55
|
-
allprojects {
|
|
56
|
-
repositories {${MAPBOX_MAVEN_BLOCK}
|
|
57
|
-
}
|
|
58
|
-
}`;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
fs.writeFileSync(settingsPath, contents);
|
|
62
|
-
return cfg;
|
|
63
|
-
},
|
|
64
|
-
]);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// ─── Plugin ─────────────────────────────────────────────────────────────
|
|
68
|
-
|
|
69
|
-
const withExpoMapboxNavigation = (config, options) => {
|
|
70
|
-
const {
|
|
71
|
-
accessToken,
|
|
72
|
-
mapboxMapsVersion = '11.11.0',
|
|
73
|
-
androidColorOverrides = {},
|
|
74
|
-
} = options;
|
|
75
|
-
|
|
76
|
-
if (!accessToken) {
|
|
77
|
-
throw new Error('[expo-mapbox-navigation] accessToken is required');
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ── iOS ───────────────────────────────────────────────────────────────
|
|
81
|
-
config = withInfoPlist(config, (cfg) => {
|
|
82
|
-
cfg.modResults.MBXAccessToken = accessToken;
|
|
83
|
-
|
|
84
|
-
cfg.modResults.NSLocationWhenInUseUsageDescription =
|
|
85
|
-
cfg.modResults.NSLocationWhenInUseUsageDescription ??
|
|
86
|
-
'Navigation GPS requires location access.';
|
|
87
|
-
|
|
88
|
-
cfg.modResults.NSLocationAlwaysAndWhenInUseUsageDescription =
|
|
89
|
-
cfg.modResults.NSLocationAlwaysAndWhenInUseUsageDescription ??
|
|
90
|
-
'Background navigation requires location access.';
|
|
91
|
-
|
|
92
|
-
cfg.modResults.NSMotionUsageDescription =
|
|
93
|
-
cfg.modResults.NSMotionUsageDescription ??
|
|
94
|
-
'Motion is used to improve navigation experience.';
|
|
95
|
-
|
|
96
|
-
const modes = cfg.modResults.UIBackgroundModes || [];
|
|
97
|
-
if (!modes.includes('audio')) modes.push('audio');
|
|
98
|
-
if (!modes.includes('location')) modes.push('location');
|
|
99
|
-
cfg.modResults.UIBackgroundModes = modes;
|
|
100
|
-
|
|
101
|
-
return cfg;
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// ── Android settings.gradle FIX (IMPORTANT SDK 53) ────────────────────
|
|
105
|
-
config = withMapboxMavenInSettings(config);
|
|
106
|
-
|
|
107
|
-
// ── Android Manifest ──────────────────────────────────────────────────
|
|
108
|
-
config = withAndroidManifest(config, (cfg) => {
|
|
109
|
-
const manifest = cfg.modResults.manifest;
|
|
110
|
-
const permissions = manifest['uses-permission'] || [];
|
|
111
|
-
|
|
112
|
-
const add = (name) => {
|
|
113
|
-
if (!permissions.find((p) => p.$?.['android:name'] === name)) {
|
|
114
|
-
permissions.push({ $: { 'android:name': name } });
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
add('android.permission.ACCESS_FINE_LOCATION');
|
|
119
|
-
add('android.permission.ACCESS_COARSE_LOCATION');
|
|
120
|
-
add('android.permission.FOREGROUND_SERVICE');
|
|
121
|
-
add('android.permission.FOREGROUND_SERVICE_LOCATION');
|
|
122
|
-
|
|
123
|
-
manifest['uses-permission'] = permissions;
|
|
124
|
-
|
|
125
|
-
const app = manifest.application?.[0];
|
|
126
|
-
if (app) {
|
|
127
|
-
const meta = app['meta-data'] || [];
|
|
128
|
-
|
|
129
|
-
if (!meta.find((m) => m.$?.['android:name'] === 'com.mapbox.token')) {
|
|
130
|
-
meta.push({
|
|
131
|
-
$: {
|
|
132
|
-
'android:name': 'com.mapbox.token',
|
|
133
|
-
'android:value': accessToken,
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
app['meta-data'] = meta;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return cfg;
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
// ── App build.gradle ──────────────────────────────────────────────────
|
|
145
|
-
config = withAppBuildGradle(config, (cfg) => {
|
|
146
|
-
if (!cfg.modResults.contents.includes('mapbox_access_token')) {
|
|
147
|
-
cfg.modResults.contents = cfg.modResults.contents.replace(
|
|
148
|
-
/defaultConfig\s*\{/,
|
|
149
|
-
`defaultConfig {
|
|
150
|
-
resValue "string", "mapbox_access_token", "${accessToken}"`
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return cfg;
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
return config;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
const plugin = createRunOncePlugin(
|
|
161
|
-
withExpoMapboxNavigation,
|
|
162
|
-
"expo-mapbox-navigation",
|
|
163
|
-
"1.0.8"
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
module.exports = plugin;
|
|
167
|
-
module.exports.default = plugin;
|