@jacques_gordon/expo-mapbox-navigation 2.0.9 → 2.1.1
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/android/build.gradle
CHANGED
|
@@ -13,12 +13,6 @@ android {
|
|
|
13
13
|
defaultConfig {
|
|
14
14
|
minSdkVersion safeExtGet("minSdkVersion", 24)
|
|
15
15
|
targetSdkVersion safeExtGet("targetSdkVersion", 35)
|
|
16
|
-
|
|
17
|
-
externalNativeBuild {
|
|
18
|
-
cmake {
|
|
19
|
-
arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
16
|
ndk {
|
|
23
17
|
abiFilters "arm64-v8a", "x86_64"
|
|
24
18
|
}
|
|
@@ -63,22 +57,26 @@ dependencies {
|
|
|
63
57
|
implementation project(':expo-modules-core')
|
|
64
58
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${safeExtGet('kotlinVersion', '1.9.0')}"
|
|
65
59
|
|
|
66
|
-
// Mapbox Navigation SDK v3
|
|
60
|
+
// Mapbox Navigation SDK v3
|
|
67
61
|
implementation "com.mapbox.navigationcore:android:${MAPBOX_NAV_VERSION}"
|
|
68
62
|
|
|
69
|
-
// Mapbox Maps SDK
|
|
63
|
+
// Mapbox Maps SDK
|
|
70
64
|
implementation("com.mapbox.maps:android:${MAPBOX_MAPS_MIN_VERSION}") {
|
|
71
65
|
transitive = true
|
|
72
66
|
}
|
|
73
67
|
|
|
74
|
-
//
|
|
75
|
-
// MapboxManeuverView — turn-by-turn banner
|
|
68
|
+
// Navigation UI Components (ManeuverView, SpeedInfoView)
|
|
76
69
|
implementation "com.mapbox.navigationcore:ui-components:${MAPBOX_NAV_VERSION}"
|
|
77
|
-
|
|
70
|
+
|
|
71
|
+
// TripData (ManeuverApi, SpeedInfoApi, TripProgressApi)
|
|
78
72
|
implementation "com.mapbox.navigationcore:tripdata:${MAPBOX_NAV_VERSION}"
|
|
79
|
-
|
|
73
|
+
|
|
74
|
+
// UI Maps (NavigationStyles, NavigationLocationProvider, NavigationCamera)
|
|
80
75
|
implementation "com.mapbox.navigationcore:ui-maps:${MAPBOX_NAV_VERSION}"
|
|
81
76
|
|
|
77
|
+
// ConstraintLayout — required because MapboxManeuverView extends ConstraintLayout
|
|
78
|
+
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
|
79
|
+
|
|
82
80
|
// AndroidX
|
|
83
81
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0'
|
|
84
82
|
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
|
|
@@ -3,20 +3,19 @@ package expo.modules.mapboxnavigation
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.graphics.Color
|
|
6
|
-
import android.os.Build
|
|
7
6
|
import android.util.Log
|
|
8
7
|
import android.view.Gravity
|
|
9
8
|
import android.view.View
|
|
10
9
|
import android.widget.FrameLayout
|
|
11
10
|
import android.widget.LinearLayout
|
|
12
11
|
import android.widget.TextView
|
|
13
|
-
import androidx.core.content.ContextCompat
|
|
14
12
|
import com.mapbox.api.directions.v5.models.RouteOptions
|
|
13
|
+
import com.mapbox.common.location.Location
|
|
15
14
|
import com.mapbox.geojson.Point
|
|
16
15
|
import com.mapbox.maps.MapView
|
|
17
|
-
import com.mapbox.maps.Style
|
|
18
16
|
import com.mapbox.maps.plugin.animation.camera
|
|
19
17
|
import com.mapbox.maps.plugin.locationcomponent.location
|
|
18
|
+
import com.mapbox.navigation.base.TimeFormat
|
|
20
19
|
import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions
|
|
21
20
|
import com.mapbox.navigation.base.formatter.DistanceFormatterOptions
|
|
22
21
|
import com.mapbox.navigation.base.options.NavigationOptions
|
|
@@ -28,6 +27,7 @@ import com.mapbox.navigation.core.MapboxNavigation
|
|
|
28
27
|
import com.mapbox.navigation.core.MapboxNavigationProvider
|
|
29
28
|
import com.mapbox.navigation.core.directions.session.RoutesObserver
|
|
30
29
|
import com.mapbox.navigation.core.directions.session.RoutesUpdatedResult
|
|
30
|
+
import com.mapbox.navigation.core.formatter.MapboxDistanceFormatter
|
|
31
31
|
import com.mapbox.navigation.core.trip.session.LocationMatcherResult
|
|
32
32
|
import com.mapbox.navigation.core.trip.session.LocationObserver
|
|
33
33
|
import com.mapbox.navigation.core.trip.session.RouteProgressObserver
|
|
@@ -47,6 +47,9 @@ import com.mapbox.navigation.ui.maps.camera.NavigationCamera
|
|
|
47
47
|
import com.mapbox.navigation.ui.maps.camera.data.MapboxNavigationViewportDataSource
|
|
48
48
|
import com.mapbox.navigation.ui.maps.camera.transition.NavigationCameraTransitionOptions
|
|
49
49
|
import com.mapbox.navigation.ui.maps.location.NavigationLocationProvider
|
|
50
|
+
import com.mapbox.navigation.ui.maps.route.arrow.api.MapboxRouteArrowApi
|
|
51
|
+
import com.mapbox.navigation.ui.maps.route.arrow.api.MapboxRouteArrowView
|
|
52
|
+
import com.mapbox.navigation.ui.maps.route.arrow.model.RouteArrowOptions
|
|
50
53
|
import com.mapbox.navigation.ui.maps.route.line.api.MapboxRouteLineApi
|
|
51
54
|
import com.mapbox.navigation.ui.maps.route.line.api.MapboxRouteLineView
|
|
52
55
|
import com.mapbox.navigation.ui.maps.route.line.model.MapboxRouteLineApiOptions
|
|
@@ -55,6 +58,7 @@ import expo.modules.kotlin.AppContext
|
|
|
55
58
|
import expo.modules.kotlin.viewevent.EventDispatcher
|
|
56
59
|
import expo.modules.kotlin.views.ExpoView
|
|
57
60
|
import java.util.Calendar
|
|
61
|
+
import java.util.Date
|
|
58
62
|
import java.util.Locale
|
|
59
63
|
|
|
60
64
|
private const val TAG = "ExpoMapboxNavigation"
|
|
@@ -70,31 +74,28 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
70
74
|
private val onRoutesFailed by EventDispatcher()
|
|
71
75
|
private val onArrival by EventDispatcher()
|
|
72
76
|
|
|
73
|
-
// ──
|
|
77
|
+
// ── Views ─────────────────────────────────────────────────────────────────
|
|
74
78
|
private val mapView: MapView = MapView(context)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
private
|
|
78
|
-
private
|
|
79
|
-
private
|
|
80
|
-
private
|
|
81
|
-
private
|
|
82
|
-
private lateinit var tvDuration: TextView
|
|
83
|
-
private lateinit var tvDistance: TextView
|
|
84
|
-
private lateinit var btnCancel: TextView
|
|
79
|
+
private var maneuverView: MapboxManeuverView? = null
|
|
80
|
+
private var speedInfoView: MapboxSpeedInfoView? = null
|
|
81
|
+
private var tripProgressView: MapboxTripProgressView? = null
|
|
82
|
+
private var tvEtaTime: TextView? = null
|
|
83
|
+
private var tvDuration: TextView? = null
|
|
84
|
+
private var tvDistance: TextView? = null
|
|
85
|
+
private var etaBar: LinearLayout? = null
|
|
85
86
|
|
|
86
87
|
// ── Navigation APIs ───────────────────────────────────────────────────────
|
|
87
|
-
private var navigationCamera: NavigationCamera
|
|
88
|
-
private var viewportDataSource: MapboxNavigationViewportDataSource
|
|
89
|
-
private var routeLineApi: MapboxRouteLineApi
|
|
90
|
-
private var routeLineView: MapboxRouteLineView
|
|
91
|
-
private var
|
|
92
|
-
private var
|
|
93
|
-
private var speedInfoApi: MapboxSpeedInfoApi
|
|
94
|
-
private
|
|
88
|
+
private lateinit var navigationCamera: NavigationCamera
|
|
89
|
+
private lateinit var viewportDataSource: MapboxNavigationViewportDataSource
|
|
90
|
+
private lateinit var routeLineApi: MapboxRouteLineApi
|
|
91
|
+
private lateinit var routeLineView: MapboxRouteLineView
|
|
92
|
+
private lateinit var maneuverApi: MapboxManeuverApi
|
|
93
|
+
private lateinit var tripProgressApi: MapboxTripProgressApi
|
|
94
|
+
private lateinit var speedInfoApi: MapboxSpeedInfoApi
|
|
95
|
+
private val routeArrowApi = MapboxRouteArrowApi()
|
|
96
|
+
private lateinit var routeArrowView: MapboxRouteArrowView
|
|
95
97
|
private val navigationLocationProvider = NavigationLocationProvider()
|
|
96
|
-
|
|
97
|
-
// ── Night mode state ──────────────────────────────────────────────────────
|
|
98
|
+
private var mapboxNavigation: MapboxNavigation? = null
|
|
98
99
|
private var isNightMode = false
|
|
99
100
|
|
|
100
101
|
// ── Props ─────────────────────────────────────────────────────────────────
|
|
@@ -113,134 +114,123 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
113
114
|
private var customRasterAboveLayerId: String? = null
|
|
114
115
|
|
|
115
116
|
init {
|
|
116
|
-
|
|
117
|
+
buildUI()
|
|
118
|
+
initAPIs()
|
|
117
119
|
setupNavigation()
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
// ─────────────────────────────────────────────────────────────────────────
|
|
121
|
-
// Build
|
|
123
|
+
// Build UI
|
|
122
124
|
// ─────────────────────────────────────────────────────────────────────────
|
|
123
|
-
private fun
|
|
125
|
+
private fun buildUI() {
|
|
126
|
+
val dp = context.resources.displayMetrics.density
|
|
124
127
|
val root = FrameLayout(context).apply {
|
|
125
128
|
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
|
126
129
|
}
|
|
127
130
|
|
|
128
|
-
|
|
129
|
-
mapView.layoutParams = FrameLayout.LayoutParams(
|
|
131
|
+
root.addView(mapView, FrameLayout.LayoutParams(
|
|
130
132
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
131
133
|
FrameLayout.LayoutParams.MATCH_PARENT
|
|
132
|
-
)
|
|
133
|
-
root.addView(mapView)
|
|
134
|
+
))
|
|
134
135
|
|
|
135
|
-
|
|
136
|
+
// ManeuverView — top (cast to View: extends ConstraintLayout)
|
|
137
|
+
val mv = MapboxManeuverView(context)
|
|
138
|
+
root.addView(mv as View, FrameLayout.LayoutParams(
|
|
139
|
+
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
140
|
+
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
141
|
+
).also { it.gravity = Gravity.TOP })
|
|
142
|
+
mv.visibility = View.INVISIBLE
|
|
143
|
+
maneuverView = mv
|
|
144
|
+
|
|
145
|
+
// SpeedInfoView — bottom-left (cast to View)
|
|
146
|
+
val siv = MapboxSpeedInfoView(context)
|
|
147
|
+
root.addView(siv as View, FrameLayout.LayoutParams(
|
|
148
|
+
FrameLayout.LayoutParams.WRAP_CONTENT,
|
|
149
|
+
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
150
|
+
).also {
|
|
151
|
+
it.gravity = Gravity.BOTTOM or Gravity.START
|
|
152
|
+
it.setMargins((16 * dp).toInt(), 0, 0, (100 * dp).toInt())
|
|
153
|
+
})
|
|
154
|
+
siv.visibility = View.GONE
|
|
155
|
+
speedInfoView = siv
|
|
136
156
|
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
141
|
-
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
142
|
-
).also { it.gravity = Gravity.TOP }
|
|
143
|
-
visibility = View.GONE
|
|
144
|
-
}
|
|
145
|
-
root.addView(maneuverView)
|
|
146
|
-
|
|
147
|
-
// ── Speed info (bottom-left, Waze style) ──────────────────────────────
|
|
148
|
-
speedInfoView = MapboxSpeedInfoView(context).apply {
|
|
149
|
-
layoutParams = FrameLayout.LayoutParams(
|
|
150
|
-
FrameLayout.LayoutParams.WRAP_CONTENT,
|
|
151
|
-
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
152
|
-
).also {
|
|
153
|
-
it.gravity = Gravity.BOTTOM or Gravity.START
|
|
154
|
-
it.setMargins(
|
|
155
|
-
(16 * dp).toInt(), 0,
|
|
156
|
-
0, (120 * dp).toInt()
|
|
157
|
-
)
|
|
158
|
-
}
|
|
159
|
-
visibility = View.GONE
|
|
160
|
-
}
|
|
161
|
-
root.addView(speedInfoView)
|
|
157
|
+
// TripProgressView (used by the official Mapbox render method)
|
|
158
|
+
val tpv = MapboxTripProgressView(context)
|
|
159
|
+
tripProgressView = tpv
|
|
162
160
|
|
|
163
|
-
//
|
|
164
|
-
|
|
161
|
+
// Bottom ETA bar
|
|
162
|
+
val bar = LinearLayout(context).apply {
|
|
165
163
|
orientation = LinearLayout.HORIZONTAL
|
|
166
164
|
setBackgroundColor(Color.WHITE)
|
|
167
165
|
elevation = 8 * dp
|
|
168
|
-
|
|
169
|
-
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
170
|
-
(80 * dp).toInt()
|
|
171
|
-
).also { it.gravity = Gravity.BOTTOM }
|
|
166
|
+
visibility = View.INVISIBLE
|
|
172
167
|
gravity = Gravity.CENTER_VERTICAL
|
|
173
168
|
setPadding(
|
|
174
169
|
(16 * dp).toInt(), (8 * dp).toInt(),
|
|
175
170
|
(16 * dp).toInt(), (8 * dp).toInt()
|
|
176
171
|
)
|
|
177
|
-
visibility = View.GONE
|
|
178
172
|
}
|
|
173
|
+
root.addView(bar, FrameLayout.LayoutParams(
|
|
174
|
+
FrameLayout.LayoutParams.MATCH_PARENT, (80 * dp).toInt()
|
|
175
|
+
).also { it.gravity = Gravity.BOTTOM })
|
|
179
176
|
|
|
180
|
-
|
|
181
|
-
tvEtaTime = TextView(context).apply {
|
|
177
|
+
val etaTime = TextView(context).apply {
|
|
182
178
|
textSize = 22f
|
|
183
179
|
setTextColor(Color.BLACK)
|
|
184
180
|
typeface = android.graphics.Typeface.DEFAULT_BOLD
|
|
185
|
-
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
|
|
186
181
|
}
|
|
187
|
-
|
|
182
|
+
bar.addView(etaTime, LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f))
|
|
183
|
+
tvEtaTime = etaTime
|
|
188
184
|
|
|
189
|
-
|
|
190
|
-
val centerLayout = LinearLayout(context).apply {
|
|
185
|
+
val center = LinearLayout(context).apply {
|
|
191
186
|
orientation = LinearLayout.VERTICAL
|
|
192
187
|
gravity = Gravity.CENTER
|
|
193
|
-
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 2f)
|
|
194
188
|
}
|
|
195
|
-
|
|
196
|
-
textSize = 16f
|
|
197
|
-
setTextColor(Color.DKGRAY)
|
|
198
|
-
gravity = Gravity.CENTER
|
|
189
|
+
val dur = TextView(context).apply {
|
|
190
|
+
textSize = 16f; setTextColor(Color.DKGRAY); gravity = Gravity.CENTER
|
|
199
191
|
}
|
|
200
|
-
|
|
201
|
-
textSize = 13f
|
|
202
|
-
setTextColor(Color.GRAY)
|
|
203
|
-
gravity = Gravity.CENTER
|
|
192
|
+
val dist = TextView(context).apply {
|
|
193
|
+
textSize = 13f; setTextColor(Color.GRAY); gravity = Gravity.CENTER
|
|
204
194
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
textSize = 22f
|
|
213
|
-
setTextColor(Color.DKGRAY)
|
|
195
|
+
center.addView(dur)
|
|
196
|
+
center.addView(dist)
|
|
197
|
+
bar.addView(center, LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 2f))
|
|
198
|
+
tvDuration = dur
|
|
199
|
+
tvDistance = dist
|
|
200
|
+
|
|
201
|
+
val cancelBtn = TextView(context).apply {
|
|
202
|
+
text = "✕"; textSize = 22f; setTextColor(Color.DKGRAY)
|
|
214
203
|
gravity = Gravity.END or Gravity.CENTER_VERTICAL
|
|
215
|
-
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
|
|
216
204
|
setOnClickListener { cancelNavigation() }
|
|
217
205
|
}
|
|
218
|
-
|
|
219
|
-
|
|
206
|
+
bar.addView(cancelBtn, LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f))
|
|
207
|
+
etaBar = bar
|
|
220
208
|
|
|
221
209
|
addView(root)
|
|
222
210
|
}
|
|
223
211
|
|
|
224
212
|
// ─────────────────────────────────────────────────────────────────────────
|
|
225
|
-
//
|
|
213
|
+
// Init APIs — confirmed from official Mapbox examples
|
|
226
214
|
// ─────────────────────────────────────────────────────────────────────────
|
|
227
|
-
private fun
|
|
228
|
-
val
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
215
|
+
private fun initAPIs() {
|
|
216
|
+
val distanceFormatterOptions = DistanceFormatterOptions.Builder(context).build()
|
|
217
|
+
|
|
218
|
+
maneuverApi = MapboxManeuverApi(MapboxDistanceFormatter(distanceFormatterOptions))
|
|
219
|
+
|
|
220
|
+
// TripProgressApi — from ShowTripProgressActivity official example
|
|
221
|
+
// PercentDistanceTraveledFormatter is optional — omit if causing issues
|
|
222
|
+
tripProgressApi = MapboxTripProgressApi(
|
|
223
|
+
TripProgressUpdateFormatter.Builder(context)
|
|
224
|
+
.distanceRemainingFormatter(DistanceRemainingFormatter(distanceFormatterOptions))
|
|
225
|
+
.timeRemainingFormatter(TimeRemainingFormatter(context))
|
|
226
|
+
.estimatedTimeToArrivalFormatter(
|
|
227
|
+
EstimatedTimeToArrivalFormatter(context, TimeFormat.NONE_SPECIFIED)
|
|
228
|
+
)
|
|
229
|
+
.build()
|
|
230
|
+
)
|
|
239
231
|
|
|
240
|
-
|
|
241
|
-
val mapboxMap = mapView.mapboxMap
|
|
232
|
+
speedInfoApi = MapboxSpeedInfoApi()
|
|
242
233
|
|
|
243
|
-
// Route line
|
|
244
234
|
routeLineApi = MapboxRouteLineApi(MapboxRouteLineApiOptions.Builder().build())
|
|
245
235
|
routeLineView = MapboxRouteLineView(
|
|
246
236
|
MapboxRouteLineViewOptions.Builder(context)
|
|
@@ -248,41 +238,38 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
248
238
|
.build()
|
|
249
239
|
)
|
|
250
240
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
241
|
+
routeArrowView = MapboxRouteArrowView(RouteArrowOptions.Builder(context).build())
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
245
|
+
// Setup Navigation
|
|
246
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
247
|
+
private fun setupNavigation() {
|
|
248
|
+
mapboxNavigation = MapboxNavigationProvider.create(
|
|
249
|
+
NavigationOptions.Builder(context).build()
|
|
257
250
|
)
|
|
258
251
|
|
|
259
|
-
|
|
260
|
-
|
|
252
|
+
mapView.mapboxMap.loadStyle(mapStyle ?: getAutoStyle()) { style ->
|
|
253
|
+
routeLineView.initializeLayers(style)
|
|
261
254
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
255
|
+
viewportDataSource = MapboxNavigationViewportDataSource(mapView.mapboxMap)
|
|
256
|
+
navigationCamera = NavigationCamera(
|
|
257
|
+
mapView.mapboxMap,
|
|
258
|
+
mapView.camera,
|
|
259
|
+
viewportDataSource
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
mapView.location.apply {
|
|
263
|
+
setLocationProvider(navigationLocationProvider)
|
|
264
|
+
enabled = true
|
|
265
|
+
}
|
|
267
266
|
|
|
268
|
-
|
|
269
|
-
val progressFormatter = TripProgressUpdateFormatter.Builder(context)
|
|
270
|
-
.distanceRemainingFormatter(DistanceRemainingFormatter(formatter))
|
|
271
|
-
.timeRemainingFormatter(TimeRemainingFormatter(context))
|
|
272
|
-
.percentRouteTraveledFormatter(PercentDistanceTraveledFormatter())
|
|
273
|
-
.estimatedTimeToArrivalFormatter(EstimatedTimeToArrivalFormatter(context))
|
|
274
|
-
.build()
|
|
275
|
-
tripProgressApi = MapboxTripProgressApi(progressFormatter)
|
|
276
|
-
|
|
277
|
-
// Location puck
|
|
278
|
-
mapView.location.apply {
|
|
279
|
-
setLocationProvider(navigationLocationProvider)
|
|
280
|
-
enabled = true
|
|
267
|
+
registerObservers()
|
|
281
268
|
}
|
|
282
269
|
}
|
|
283
270
|
|
|
284
271
|
// ─────────────────────────────────────────────────────────────────────────
|
|
285
|
-
//
|
|
272
|
+
// Observers
|
|
286
273
|
// ─────────────────────────────────────────────────────────────────────────
|
|
287
274
|
private fun registerObservers() {
|
|
288
275
|
val nav = mapboxNavigation ?: return
|
|
@@ -290,73 +277,76 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
290
277
|
// Routes observer
|
|
291
278
|
nav.registerRoutesObserver(object : RoutesObserver {
|
|
292
279
|
override fun onRoutesChanged(result: RoutesUpdatedResult) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
routeLineView?.renderRouteDrawData(style, value)
|
|
280
|
+
if (result.navigationRoutes.isNotEmpty()) {
|
|
281
|
+
routeLineApi.setNavigationRoutes(result.navigationRoutes) { value ->
|
|
282
|
+
mapView.mapboxMap.style?.apply {
|
|
283
|
+
routeLineView.renderRouteDrawData(this, value)
|
|
298
284
|
}
|
|
299
285
|
}
|
|
300
|
-
viewportDataSource
|
|
301
|
-
viewportDataSource
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
// Show UI overlays
|
|
305
|
-
maneuverView.visibility = View.VISIBLE
|
|
306
|
-
etaBottomBar.visibility = View.VISIBLE
|
|
307
|
-
|
|
286
|
+
viewportDataSource.onRouteChanged(result.navigationRoutes.first())
|
|
287
|
+
viewportDataSource.evaluate()
|
|
288
|
+
showUI()
|
|
308
289
|
onRoutesReady(mapOf(
|
|
309
|
-
"routeCount" to
|
|
310
|
-
"distanceMeters" to (
|
|
311
|
-
"durationSeconds" to (
|
|
290
|
+
"routeCount" to result.navigationRoutes.size,
|
|
291
|
+
"distanceMeters" to (result.navigationRoutes.first().directionsRoute.distance() ?: 0.0),
|
|
292
|
+
"durationSeconds" to (result.navigationRoutes.first().directionsRoute.duration() ?: 0.0)
|
|
312
293
|
))
|
|
313
294
|
} else {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
routeLineView
|
|
295
|
+
mapView.mapboxMap.style?.let { style ->
|
|
296
|
+
routeLineApi.clearRouteLine { value ->
|
|
297
|
+
routeLineView.renderClearRouteLineValue(style, value)
|
|
317
298
|
}
|
|
299
|
+
routeArrowView.render(style, routeArrowApi.clearArrows())
|
|
318
300
|
}
|
|
319
|
-
viewportDataSource
|
|
320
|
-
viewportDataSource
|
|
321
|
-
|
|
301
|
+
viewportDataSource.clearRouteData()
|
|
302
|
+
viewportDataSource.evaluate()
|
|
303
|
+
hideUI()
|
|
322
304
|
}
|
|
323
305
|
}
|
|
324
306
|
})
|
|
325
307
|
|
|
326
|
-
// Route progress observer
|
|
308
|
+
// Route progress observer
|
|
327
309
|
nav.registerRouteProgressObserver(RouteProgressObserver { routeProgress ->
|
|
328
|
-
viewportDataSource
|
|
329
|
-
viewportDataSource
|
|
310
|
+
viewportDataSource.onRouteProgressChanged(routeProgress)
|
|
311
|
+
viewportDataSource.evaluate()
|
|
330
312
|
|
|
331
|
-
//
|
|
332
|
-
|
|
333
|
-
|
|
313
|
+
// Route arrow
|
|
314
|
+
mapView.mapboxMap.style?.let { style ->
|
|
315
|
+
val arrowResult = routeArrowApi.addUpcomingManeuverArrow(routeProgress)
|
|
316
|
+
routeArrowView.renderManeuverUpdate(style, arrowResult)
|
|
334
317
|
}
|
|
335
318
|
|
|
336
|
-
// ──
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
319
|
+
// ── Maneuver — fold() with explicit Unit returns on both branches ──
|
|
320
|
+
// Fix for error: "Argument type mismatch: Unit? but R & Any expected"
|
|
321
|
+
// Solution: use explicit return type annotation on the success lambda
|
|
322
|
+
val maneuvers = maneuverApi.getManeuvers(routeProgress)
|
|
323
|
+
maneuvers.fold(
|
|
324
|
+
{ error ->
|
|
325
|
+
Log.w(TAG, "Maneuver error: ${error.errorMessage}")
|
|
326
|
+
Unit
|
|
327
|
+
},
|
|
328
|
+
{ _ ->
|
|
329
|
+
maneuverView?.visibility = View.VISIBLE
|
|
330
|
+
maneuverView?.renderManeuvers(maneuvers)
|
|
331
|
+
Unit
|
|
341
332
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
// ── Trip progress — use getTripProgress exactly as official example ──
|
|
336
|
+
// render() to the MapboxTripProgressView (official pattern)
|
|
337
|
+
// For our custom ETA bar, use the raw fields from TripProgressUpdateValue:
|
|
338
|
+
// .estimatedTimeToArrival — Long (Unix timestamp ms of arrival)
|
|
339
|
+
// .currentLegTimeRemaining — Double (seconds remaining for current leg)
|
|
340
|
+
// .totalTimeRemaining — Double (seconds remaining total)
|
|
341
|
+
// .distanceRemaining — Double (metres remaining)
|
|
342
|
+
val tripProgress = tripProgressApi.getTripProgress(routeProgress)
|
|
343
|
+
tripProgressView?.render(tripProgress)
|
|
344
|
+
updateEtaBar(
|
|
345
|
+
tripProgress.estimatedTimeToArrival,
|
|
346
|
+
tripProgress.totalTimeRemaining,
|
|
347
|
+
tripProgress.distanceRemaining
|
|
348
|
+
)
|
|
358
349
|
|
|
359
|
-
// ── Emit progress event ───────────────────────────────────────
|
|
360
350
|
onRouteProgressChanged(mapOf(
|
|
361
351
|
"distanceRemaining" to routeProgress.distanceRemaining,
|
|
362
352
|
"durationRemaining" to routeProgress.durationRemaining,
|
|
@@ -368,124 +358,133 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
368
358
|
))
|
|
369
359
|
})
|
|
370
360
|
|
|
371
|
-
// Location observer
|
|
361
|
+
// Location observer
|
|
372
362
|
nav.registerLocationObserver(object : LocationObserver {
|
|
373
|
-
override fun onNewRawLocation(rawLocation:
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
val enhancedLocation = locationMatcherResult.enhancedLocation
|
|
377
|
-
|
|
378
|
-
// Update location puck
|
|
363
|
+
override fun onNewRawLocation(rawLocation: Location) {}
|
|
364
|
+
override fun onNewLocationMatcherResult(result: LocationMatcherResult) {
|
|
365
|
+
val loc = result.enhancedLocation
|
|
379
366
|
navigationLocationProvider.changePosition(
|
|
380
|
-
location =
|
|
381
|
-
keyPoints =
|
|
382
|
-
)
|
|
383
|
-
|
|
384
|
-
// Update camera
|
|
385
|
-
viewportDataSource?.onLocationChanged(enhancedLocation)
|
|
386
|
-
viewportDataSource?.evaluate()
|
|
387
|
-
|
|
388
|
-
// ── Speed limit (issue — show posted + current speed) ──────
|
|
389
|
-
val formatter = DistanceFormatterOptions.Builder(context).build()
|
|
390
|
-
val info = speedInfoApi?.updatePostedAndCurrentSpeed(
|
|
391
|
-
locationMatcherResult,
|
|
392
|
-
formatter
|
|
367
|
+
location = loc,
|
|
368
|
+
keyPoints = result.keyPoints,
|
|
393
369
|
)
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
370
|
+
viewportDataSource.onLocationChanged(loc)
|
|
371
|
+
viewportDataSource.evaluate()
|
|
372
|
+
|
|
373
|
+
// Speed limit
|
|
374
|
+
val fmtOptions = DistanceFormatterOptions.Builder(context).build()
|
|
375
|
+
val speedInfo = speedInfoApi.updatePostedAndCurrentSpeed(result, fmtOptions)
|
|
376
|
+
if (speedInfo != null) {
|
|
377
|
+
speedInfoView?.visibility = View.VISIBLE
|
|
378
|
+
speedInfoView?.render(speedInfo)
|
|
397
379
|
} else {
|
|
398
|
-
speedInfoView
|
|
380
|
+
speedInfoView?.visibility = View.GONE
|
|
399
381
|
}
|
|
400
382
|
|
|
401
|
-
// ── Auto day/night switch ──────────────────────────────────
|
|
402
383
|
checkAndSwitchDayNight()
|
|
403
384
|
}
|
|
404
385
|
})
|
|
405
386
|
}
|
|
406
387
|
|
|
407
388
|
// ─────────────────────────────────────────────────────────────────────────
|
|
408
|
-
//
|
|
389
|
+
// ETA bar — using confirmed TripProgressUpdateValue fields
|
|
390
|
+
// estimatedTimeToArrival: Long — Unix timestamp (ms) of expected arrival
|
|
391
|
+
// totalTimeRemaining: Double — seconds remaining
|
|
392
|
+
// distanceRemaining: Double — metres remaining
|
|
393
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
394
|
+
private fun updateEtaBar(
|
|
395
|
+
estimatedTimeToArrivalMs: Long,
|
|
396
|
+
totalTimeRemainingSec: Double,
|
|
397
|
+
distanceRemainingMetres: Double
|
|
398
|
+
) {
|
|
399
|
+
// Arrival clock time from Unix timestamp
|
|
400
|
+
val arrivalCal = Calendar.getInstance().apply {
|
|
401
|
+
timeInMillis = estimatedTimeToArrivalMs
|
|
402
|
+
}
|
|
403
|
+
tvEtaTime?.text = String.format(
|
|
404
|
+
"%02d:%02d",
|
|
405
|
+
arrivalCal.get(Calendar.HOUR_OF_DAY),
|
|
406
|
+
arrivalCal.get(Calendar.MINUTE)
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
// Duration remaining
|
|
410
|
+
val totalMin = (totalTimeRemainingSec / 60).toInt()
|
|
411
|
+
tvDuration?.text = if (totalMin >= 60)
|
|
412
|
+
"${totalMin / 60}h ${totalMin % 60}min"
|
|
413
|
+
else
|
|
414
|
+
"${totalMin} min"
|
|
415
|
+
|
|
416
|
+
// Distance remaining
|
|
417
|
+
tvDistance?.text = if (distanceRemainingMetres >= 1000)
|
|
418
|
+
String.format("%.1f km", distanceRemainingMetres / 1000.0)
|
|
419
|
+
else
|
|
420
|
+
"${distanceRemainingMetres.toInt()} m"
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
424
|
+
// Day / Night
|
|
409
425
|
// ─────────────────────────────────────────────────────────────────────────
|
|
410
426
|
private fun getAutoStyle(): String {
|
|
411
427
|
val hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
|
|
412
|
-
return if (hour in 6..20)
|
|
413
|
-
|
|
414
|
-
else
|
|
415
|
-
NavigationStyles.NAVIGATION_NIGHT_STYLE
|
|
428
|
+
return if (hour in 6..20) NavigationStyles.NAVIGATION_DAY_STYLE
|
|
429
|
+
else NavigationStyles.NAVIGATION_NIGHT_STYLE
|
|
416
430
|
}
|
|
417
431
|
|
|
418
432
|
private fun checkAndSwitchDayNight() {
|
|
419
433
|
val hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
|
|
420
434
|
val shouldBeNight = hour !in 6..20
|
|
421
|
-
if (shouldBeNight
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
mapView.mapboxMap.style?.let { style ->
|
|
431
|
-
routeLineApi?.let { api ->
|
|
432
|
-
mapboxNavigation?.getNavigationRoutes()?.let { routes ->
|
|
433
|
-
if (routes.isNotEmpty()) {
|
|
434
|
-
api.setNavigationRoutes(routes) { value ->
|
|
435
|
-
routeLineView?.renderRouteDrawData(style, value)
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
435
|
+
if (shouldBeNight == isNightMode) return
|
|
436
|
+
isNightMode = shouldBeNight
|
|
437
|
+
val newStyle = if (shouldBeNight) NavigationStyles.NAVIGATION_NIGHT_STYLE
|
|
438
|
+
else NavigationStyles.NAVIGATION_DAY_STYLE
|
|
439
|
+
mapView.mapboxMap.loadStyle(newStyle) { style ->
|
|
440
|
+
routeLineView.initializeLayers(style)
|
|
441
|
+
mapboxNavigation?.getNavigationRoutes()?.takeIf { it.isNotEmpty() }?.let { routes ->
|
|
442
|
+
routeLineApi.setNavigationRoutes(routes) { value ->
|
|
443
|
+
routeLineView.renderRouteDrawData(style, value)
|
|
440
444
|
}
|
|
441
445
|
}
|
|
442
|
-
|
|
443
|
-
// Switch bottom bar color
|
|
444
|
-
etaBottomBar.setBackgroundColor(
|
|
445
|
-
if (shouldBeNight) Color.parseColor("#1E2433") else Color.WHITE
|
|
446
|
-
)
|
|
447
|
-
val textColor = if (shouldBeNight) Color.WHITE else Color.BLACK
|
|
448
|
-
tvEtaTime.setTextColor(textColor)
|
|
449
|
-
tvDuration.setTextColor(if (shouldBeNight) Color.LTGRAY else Color.DKGRAY)
|
|
450
|
-
tvDistance.setTextColor(if (shouldBeNight) Color.GRAY else Color.GRAY)
|
|
451
|
-
btnCancel.setTextColor(if (shouldBeNight) Color.LTGRAY else Color.DKGRAY)
|
|
452
446
|
}
|
|
447
|
+
etaBar?.setBackgroundColor(if (shouldBeNight) Color.parseColor("#1E2433") else Color.WHITE)
|
|
448
|
+
val tc = if (shouldBeNight) Color.WHITE else Color.BLACK
|
|
449
|
+
tvEtaTime?.setTextColor(tc)
|
|
450
|
+
tvDuration?.setTextColor(if (shouldBeNight) Color.LTGRAY else Color.DKGRAY)
|
|
451
|
+
tvDistance?.setTextColor(Color.GRAY)
|
|
453
452
|
}
|
|
454
453
|
|
|
455
454
|
// ─────────────────────────────────────────────────────────────────────────
|
|
456
455
|
// Cancel navigation
|
|
457
456
|
// ─────────────────────────────────────────────────────────────────────────
|
|
458
457
|
private fun cancelNavigation() {
|
|
459
|
-
mapboxNavigation?.setNavigationRoutes(
|
|
458
|
+
mapboxNavigation?.setNavigationRoutes(listOf())
|
|
460
459
|
mapboxNavigation?.stopTripSession()
|
|
461
|
-
|
|
460
|
+
hideUI()
|
|
462
461
|
onNavigationCancelled(mapOf<String, Any>())
|
|
463
462
|
}
|
|
464
463
|
|
|
465
|
-
private fun
|
|
466
|
-
maneuverView
|
|
467
|
-
|
|
468
|
-
etaBottomBar.visibility = View.GONE
|
|
464
|
+
private fun showUI() {
|
|
465
|
+
maneuverView?.visibility = View.VISIBLE
|
|
466
|
+
etaBar?.visibility = View.VISIBLE
|
|
469
467
|
}
|
|
470
468
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
469
|
+
private fun hideUI() {
|
|
470
|
+
maneuverView?.visibility = View.INVISIBLE
|
|
471
|
+
speedInfoView?.visibility = View.GONE
|
|
472
|
+
etaBar?.visibility = View.INVISIBLE
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Issue #43
|
|
474
476
|
private fun safeCameraFollowing() {
|
|
475
477
|
try {
|
|
476
|
-
navigationCamera
|
|
478
|
+
navigationCamera.requestNavigationCameraToFollowing(
|
|
477
479
|
stateTransitionOptions = NavigationCameraTransitionOptions.Builder()
|
|
478
|
-
.maxDuration(0)
|
|
479
|
-
.build()
|
|
480
|
+
.maxDuration(0).build()
|
|
480
481
|
)
|
|
481
482
|
} catch (e: Exception) {
|
|
482
|
-
Log.e(TAG, "Camera
|
|
483
|
+
Log.e(TAG, "Camera error: ${e.message}")
|
|
483
484
|
}
|
|
484
485
|
}
|
|
485
486
|
|
|
486
|
-
//
|
|
487
|
-
// Issue #31: voice units
|
|
488
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
487
|
+
// Issue #31
|
|
489
488
|
private fun resolveVoiceUnits(): String {
|
|
490
489
|
return when (voiceUnits?.lowercase()) {
|
|
491
490
|
"metric" -> "metric"
|
|
@@ -497,76 +496,44 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
497
496
|
}
|
|
498
497
|
}
|
|
499
498
|
|
|
500
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
501
499
|
// Route request
|
|
502
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
503
500
|
@SuppressLint("MissingPermission")
|
|
504
501
|
private fun fetchRoutes() {
|
|
505
502
|
val nav = mapboxNavigation ?: return
|
|
506
503
|
if (coordinates.size < 2) return
|
|
507
|
-
|
|
508
|
-
val points = coordinates.map { coord ->
|
|
509
|
-
Point.fromLngLat(coord["longitude"] ?: 0.0, coord["latitude"] ?: 0.0)
|
|
510
|
-
}
|
|
504
|
+
val points = coordinates.map { Point.fromLngLat(it["longitude"] ?: 0.0, it["latitude"] ?: 0.0) }
|
|
511
505
|
val locale = language?.let { Locale.forLanguageTag(it) } ?: Locale.getDefault()
|
|
512
|
-
|
|
513
506
|
val builder = RouteOptions.builder()
|
|
514
507
|
.applyDefaultNavigationOptions()
|
|
515
508
|
.language(locale.toLanguageTag())
|
|
516
509
|
.voiceUnits(resolveVoiceUnits())
|
|
517
510
|
.coordinatesList(points)
|
|
518
|
-
// maxspeed annotation required for speed limit display
|
|
519
511
|
.annotations("maxspeed,congestion,duration")
|
|
520
|
-
|
|
521
512
|
waypointIndices?.let { builder.waypointIndicesList(it) }
|
|
522
|
-
navigationProfile?.let {
|
|
523
|
-
|
|
524
|
-
}
|
|
525
|
-
excludeTypes?.takeIf { it.isNotEmpty() }?.let {
|
|
526
|
-
builder.exclude(it.joinToString(","))
|
|
527
|
-
}
|
|
513
|
+
navigationProfile?.let { builder.profile(if (it.startsWith("mapbox/")) it else "mapbox/$it") }
|
|
514
|
+
excludeTypes?.takeIf { it.isNotEmpty() }?.let { builder.exclude(it.joinToString(",")) }
|
|
528
515
|
maxHeight?.let { builder.maxHeight(it) }
|
|
529
516
|
maxWidth?.let { builder.maxWidth(it) }
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
@RouterOrigin routerOrigin: String
|
|
537
|
-
) {
|
|
538
|
-
if (routes.isEmpty()) {
|
|
539
|
-
onRoutesFailed(mapOf("message" to "No routes returned"))
|
|
540
|
-
return
|
|
541
|
-
}
|
|
542
|
-
nav.setNavigationRoutes(routes)
|
|
543
|
-
nav.startTripSession()
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
override fun onFailure(
|
|
547
|
-
reasons: List<RouterFailure>,
|
|
548
|
-
routeOptions: RouteOptions
|
|
549
|
-
) {
|
|
550
|
-
val msg = reasons.firstOrNull()?.message ?: "Unknown error"
|
|
551
|
-
Log.e(TAG, "Route request failed: $msg")
|
|
552
|
-
onRoutesFailed(mapOf("message" to msg))
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
override fun onCanceled(
|
|
556
|
-
routeOptions: RouteOptions,
|
|
557
|
-
@RouterOrigin routerOrigin: String
|
|
558
|
-
) {
|
|
559
|
-
Log.d(TAG, "Route request cancelled")
|
|
560
|
-
}
|
|
517
|
+
nav.requestRoutes(builder.build(), object : NavigationRouterCallback {
|
|
518
|
+
override fun onRoutesReady(routes: List<NavigationRoute>, @RouterOrigin routerOrigin: String) {
|
|
519
|
+
if (routes.isEmpty()) { onRoutesFailed(mapOf("message" to "No routes returned")); return }
|
|
520
|
+
nav.setNavigationRoutes(routes)
|
|
521
|
+
nav.startTripSession()
|
|
522
|
+
safeCameraFollowing()
|
|
561
523
|
}
|
|
562
|
-
|
|
524
|
+
override fun onFailure(reasons: List<RouterFailure>, routeOptions: RouteOptions) {
|
|
525
|
+
val msg = reasons.firstOrNull()?.message ?: "Unknown error"
|
|
526
|
+
Log.e(TAG, "Route failed: $msg")
|
|
527
|
+
onRoutesFailed(mapOf("message" to msg))
|
|
528
|
+
}
|
|
529
|
+
override fun onCanceled(routeOptions: RouteOptions, @RouterOrigin routerOrigin: String) {
|
|
530
|
+
Log.d(TAG, "Route cancelled")
|
|
531
|
+
}
|
|
532
|
+
})
|
|
563
533
|
}
|
|
564
534
|
|
|
565
|
-
//
|
|
566
|
-
fun setCoordinates(coords: List<Map<String, Double>>) {
|
|
567
|
-
coordinates = coords
|
|
568
|
-
if (coords.size >= 2) fetchRoutes()
|
|
569
|
-
}
|
|
535
|
+
// Prop setters
|
|
536
|
+
fun setCoordinates(coords: List<Map<String, Double>>) { coordinates = coords; if (coords.size >= 2) fetchRoutes() }
|
|
570
537
|
fun setWaypointIndices(indices: List<Int>?) { waypointIndices = indices }
|
|
571
538
|
fun setLanguage(lang: String?) { language = lang }
|
|
572
539
|
fun setVoiceUnits(units: String?) { voiceUnits = units }
|
|
@@ -580,12 +547,11 @@ class ExpoMapboxNavigationView(context: Context, appContext: AppContext) :
|
|
|
580
547
|
fun setCustomRasterTileUrl(url: String?) { customRasterTileUrl = url }
|
|
581
548
|
fun setCustomRasterAboveLayerId(layerId: String?) { customRasterAboveLayerId = layerId }
|
|
582
549
|
|
|
583
|
-
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
|
584
550
|
override fun onDetachedFromWindow() {
|
|
585
551
|
super.onDetachedFromWindow()
|
|
586
|
-
maneuverApi
|
|
587
|
-
routeLineApi
|
|
588
|
-
routeLineView
|
|
552
|
+
maneuverApi.cancel()
|
|
553
|
+
routeLineApi.cancel()
|
|
554
|
+
routeLineView.cancel()
|
|
589
555
|
mapboxNavigation?.stopTripSession()
|
|
590
556
|
MapboxNavigationProvider.destroy()
|
|
591
557
|
mapView.onStop()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jacques_gordon/expo-mapbox-navigation",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Expo module for Mapbox Navigation SDK with 16KB page size support, NDK27, and Mapbox Maps v11.11.0+",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
],
|
|
24
24
|
"repository": {
|
|
25
25
|
"type": "git",
|
|
26
|
-
"url": "https://github.com/
|
|
26
|
+
"url": "https://github.com/jacquesngomeheffa/expo-mapbox-navigation.git"
|
|
27
27
|
},
|
|
28
28
|
"bugs": {
|
|
29
|
-
"url": "https://github.com/
|
|
29
|
+
"url": "https://github.com/jacquesngomeheffa/expo-mapbox-navigation/issues"
|
|
30
30
|
},
|
|
31
31
|
"author": "Jacques Gordon",
|
|
32
32
|
"license": "MIT",
|
|
33
|
-
"homepage": "https://github.com/
|
|
33
|
+
"homepage": "https://github.com/jacquesngomeheffa/expo-mapbox-navigation#readme",
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"expo": ">=53.0.0",
|
|
36
36
|
"react": "*",
|