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 {