diff --git a/docs/Camera.md b/docs/Camera.md
index 5dc3e1389..c2a438861 100644
--- a/docs/Camera.md
+++ b/docs/Camera.md
@@ -60,7 +60,7 @@ return (
| animationMode | `union` | `none` | `false` | The easing or path the camera uses to animate to a new configuration. |
| allowUpdates | `boolean` | `none` | `false` | Whether the camera should send any configuration to the native module. Prevents unnecessary tile
fetching and improves performance when the map is not visible. Defaults to `true`. |
| triggerKey | `string \| number` | `none` | `false` | Any arbitrary primitive value that, when changed, causes the camera to retry moving to its target
configuration. (Not yet implemented.) |
-| onUserTrackingModeChange | `UserTrackingModeChangeCallback` | `none` | `false` | Executes when user tracking mode changes. |
+| onUserTrackingModeChange | `func` | `none` | `false` | Executes when user tracking mode changes.
*signature:*`(event:MapboxGLEvent) => void` |
## methods
### setCamera()
diff --git a/docs/docs.json b/docs/docs.json
index 6f58ddfe4..820e9839a 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -696,9 +696,12 @@
{
"name": "onUserTrackingModeChange",
"required": false,
- "type": "UserTrackingModeChangeCallback",
+ "type": {
+ "name": "func",
+ "funcSignature": "(event:MapboxGLEvent) => void"
+ },
"default": "none",
- "description": "Executes when user tracking mode changes."
+ "description": "Executes when user tracking mode changes.\n*signature:*`(event:MapboxGLEvent) => void`"
}
],
"fileNameWithExt": "Camera.tsx",
diff --git a/index.d.ts b/index.d.ts
index caefc7fb6..90d453d5b 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -32,14 +32,14 @@ import {
CameraBoundsWithPadding as _CameraBoundsWithPadding,
CameraStops as _CameraStops,
CameraAnimationMode as _CameraAnimationMode,
+ type UserTrackingMode as _UserTrackingMode,
+ type UserTrackingModeChangeCallback as _UserTrackingModeChangeCallback,
} from './javascript/components/Camera';
import { MarkerView as _MarkerView } from './javascript/components/MarkerView';
import { PointAnnotation as _PointAnnotation } from './javascript/components/PointAnnotation';
import { Atmosphere as _Atmosphere } from './javascript/components/Atmosphere';
import type {
MapboxGLEvent as _MapboxGLEvent,
- UserTrackingMode as _UserTrackingMode,
- UserTrackingModeChangeCallback as _UserTrackingModeChangeCallback,
AnimatedPoint as _AnimatedPoint,
AnimatedShape as _AnimatedShape,
} from './javascript/types/index';
@@ -482,11 +482,6 @@ declare namespace MapboxGL {
/**
* Constants
*/
- enum UserTrackingModes {
- Follow = 'normal',
- FollowWithHeading = 'compass',
- FollowWithCourse = 'course',
- }
enum InterpolationMode {
Exponential = 0,
diff --git a/ios/RCTMGL-v10/RCTMGLCamera.swift b/ios/RCTMGL-v10/RCTMGLCamera.swift
index a0bb75ba4..e0239ba73 100644
--- a/ios/RCTMGL-v10/RCTMGLCamera.swift
+++ b/ios/RCTMGL-v10/RCTMGLCamera.swift
@@ -13,6 +13,10 @@ enum CameraMode: String, CaseIterable {
case flight, ease, linear, none
}
+enum UserTrackingMode: String {
+ case none,compass, course, normal
+}
+
struct CameraUpdateItem {
var camera: CameraOptions
var mode: CameraMode
@@ -133,7 +137,7 @@ class RCTMGLCamera : RCTMGLMapComponentBase, LocationConsumer {
_updateCameraFromTrackingMode()
}
}
- @objc var followUserMode: NSString? {
+ @objc var followUserMode: String? {
didSet {
_updateCameraFromTrackingMode()
}
@@ -192,11 +196,22 @@ class RCTMGLCamera : RCTMGLMapComponentBase, LocationConsumer {
}
}
+ func _disableUsetTracking(_ map: MapView) {
+ map.viewport.idle()
+ map.location.removeLocationConsumer(consumer: self)
+ }
+
func _updateCameraFromTrackingMode() {
withMapView { map in
- guard self.followUserLocation else {
- map.viewport.idle()
- map.location.removeLocationConsumer(consumer: self)
+ let userTrackingMode = UserTrackingMode(rawValue: self.followUserMode ?? "none")
+ guard let userTrackingMode = userTrackingMode else {
+ Logger.error("RCTMGLCamera: Unexpected followUserMode \(optional: self.followUserMode)")
+ self._disableUsetTracking(map)
+ return
+ }
+
+ guard self.followUserLocation && userTrackingMode != .none else {
+ self._disableUsetTracking(map)
return
}
@@ -207,17 +222,20 @@ class RCTMGLCamera : RCTMGLMapComponentBase, LocationConsumer {
map.location.addLocationConsumer(newConsumer: self)
var trackingModeChanged = false
var followOptions = FollowPuckViewportStateOptions()
- if (self.followUserMode == "compass") {
+ switch userTrackingMode {
+ case .none:
+ Logger.assert("RCTMGLCamera, userTrackingModes should not be none here")
+ case .compass:
map.location.options.puckBearingEnabled = true
map.location.options.puckBearingSource = PuckBearingSource.heading
followOptions.bearing = FollowPuckViewportStateBearing.heading
trackingModeChanged = true
- } else if (self.followUserMode == "course") {
+ case .course:
map.location.options.puckBearingEnabled = true
map.location.options.puckBearingSource = PuckBearingSource.course
followOptions.bearing = FollowPuckViewportStateBearing.course
trackingModeChanged = true
- } else if (self.followUserMode == "normal") {
+ case .normal:
map.location.options.puckBearingEnabled = false
followOptions.bearing = nil
trackingModeChanged = true
diff --git a/ios/RCTMGL-v10/RCTMGLLogging.swift b/ios/RCTMGL-v10/RCTMGLLogging.swift
index 7e6a55e64..918fab039 100644
--- a/ios/RCTMGL-v10/RCTMGLLogging.swift
+++ b/ios/RCTMGL-v10/RCTMGLLogging.swift
@@ -63,6 +63,14 @@ class Logger {
static func log(level: LogLevel, message: String, error: Error) {
sharedInstance.log(level: level, message: "\(message) - error: \(error.localizedDescription) \(error)")
}
+
+ static func error(_ message: String) {
+ log(level: .error, message: message)
+ }
+
+ static func assert(_ message: String) {
+ log(level: .error, message: "Assertion failure: \(message)")
+ }
}
func logged(_ msg: String, info: (() -> String)? = nil, level: Logger.LogLevel = .error, rejecter: RCTPromiseRejectBlock? = nil, fn : () throws -> T) -> T? {
diff --git a/javascript/components/Camera.tsx b/javascript/components/Camera.tsx
index dad314d4c..c989314a5 100644
--- a/javascript/components/Camera.tsx
+++ b/javascript/components/Camera.tsx
@@ -9,11 +9,27 @@ import React, {
import { NativeModules, requireNativeComponent } from 'react-native';
import { Position } from '@turf/helpers';
-import { UserTrackingModeChangeCallback, UserTrackingMode } from '../types';
+import { MapboxGLEvent } from '../types';
import { makeLatLngBounds, makePoint } from '../utils/geoUtils';
const NativeModule = NativeModules.MGLModule;
+export const enum UserTrackingMode {
+ Follow = 'normal',
+ FollowWithHeading = 'compass',
+ FollowWithCourse = 'course',
+}
+
+export type UserTrackingModeChangeCallback = (
+ event: MapboxGLEvent<
+ 'usertrackingmodechange',
+ {
+ followUserLocation: boolean;
+ followUserMode: UserTrackingMode | null;
+ }
+ >,
+) => void;
+
/**
* Converts the provided React Native animation mode into the corresponding native enum value.
*/
diff --git a/javascript/index.js b/javascript/index.js
index d481cc399..aafc765fa 100644
--- a/javascript/index.js
+++ b/javascript/index.js
@@ -1,6 +1,6 @@
import { NativeModules } from 'react-native';
-import { Camera } from './components/Camera';
+import { Camera, UserTrackingModes } from './components/Camera';
import { Atmosphere } from './components/Atmosphere';
import MapView from './components/MapView';
import Light from './components/Light';
@@ -45,7 +45,7 @@ const MapboxGL = { ...NativeModules.MGLModule };
// static methods
MapboxGL.requestAndroidLocationPermissions = requestAndroidLocationPermissions;
-MapboxGL.UserTrackingModes = Camera.UserTrackingModes;
+MapboxGL.UserTrackingModes = UserTrackingModes;
// components
MapboxGL.MapView = MapView;
diff --git a/javascript/types/index.ts b/javascript/types/index.ts
index 04b94a62d..c271efa6b 100644
--- a/javascript/types/index.ts
+++ b/javascript/types/index.ts
@@ -10,20 +10,6 @@ export type MapboxGLEvent<
V = Element,
> = SyntheticEvent;
-// Camera.
-
-export type UserTrackingMode = 'normal' | 'compass' | 'course';
-
-export type UserTrackingModeChangeCallback = (
- event: MapboxGLEvent<
- 'usertrackingmodechange',
- {
- followUserLocation: boolean;
- followUserMode: UserTrackingMode | null;
- }
- >,
-) => void;
-
// Animated.
export interface AnimatedPoint extends GeoJsonObject {