Skip to content

Commit

Permalink
feat(ios,v11): implement location module on v11 (#3085)
Browse files Browse the repository at this point in the history
  • Loading branch information
mfazekas authored Sep 28, 2023
1 parent 4510398 commit 55fa797
Show file tree
Hide file tree
Showing 6 changed files with 311 additions and 98 deletions.
13 changes: 8 additions & 5 deletions example/src/examples/UserLocation/UserLocationUpdates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ import { Text } from 'react-native';
import MapboxGL, { Location } from '@rnmapbox/maps';

import sheet from '../../styles/sheet';
import { BaseExampleProps } from '../common/BaseExamplePropTypes';
import Page from '../common/Page';
import Bubble from '../common/Bubble';

const UserLocationUpdates = (props: BaseExampleProps) => {
const UserLocationUpdates = () => {
const [location, setLocation] = useState<Location>();

return (
<Page {...props}>
<>
<MapboxGL.MapView style={sheet.matchParent}>
<MapboxGL.UserLocation
onUpdate={(newLocation) => setLocation(newLocation)}
Expand All @@ -32,8 +30,13 @@ const UserLocationUpdates = (props: BaseExampleProps) => {
</>
)}
</Bubble>
</Page>
</>
);
};

UserLocationUpdates.title = 'User Location Updates';
UserLocationUpdates.tags = ['UserLocation', 'UserLocation#onUpdate'];
UserLocationUpdates.docs =
'Retrieves and shows location updates from UserLocation componen via the `onUpdate` callback';

export default UserLocationUpdates;
17 changes: 8 additions & 9 deletions example/src/examples/V11/StyleImportConfig.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import React, { useState } from 'react';
import { Button, SafeAreaView } from 'react-native';
import { Button } from 'react-native';
import { MapView, StyleImport, Camera } from '@rnmapbox/maps';

const styles = {
mapView: { flex: 1 },
};

const StyleImportConfig = () => {
const [lightPreset, setLightPreset] = useState('night');
console.log('# lightPreset', lightPreset);
const nextLightPreset = lightPreset === 'night' ? 'day' : 'night';
return (
<SafeAreaView style={{ flex: 1 }}>
<>
<Button
title={`Change to ${nextLightPreset}`}
onPress={() => {
Expand All @@ -23,7 +18,7 @@ const StyleImportConfig = () => {
styleURL={'mapbox://styles/mapbox/standard-beta'}
>
<Camera
centerCoordinate={[-74.00597, 40.71427]}
defaultSettings={{ centerCoordinate: [-74.00597, 40.71427] }}
zoomLevel={18}
pitch={33}
/>
Expand All @@ -35,10 +30,14 @@ const StyleImportConfig = () => {
}}
/>
</MapView>
</SafeAreaView>
</>
);
};

const styles = {
mapView: { flex: 1 },
};

StyleImportConfig.title = 'Style Import Config';
StyleImportConfig.tags = ['StyleImport', 'v11'];
StyleImportConfig.docs = `
Expand Down
27 changes: 22 additions & 5 deletions example/src/scenes/GroupAndItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,13 @@ const styles = StyleSheet.create({

type NavigationType = 'Group' | 'Item';

type ItemComponent = React.ComponentType<{
type ItemComponentProps = {
label: string;
onDismissExample: () => void;
navigation: ItemProps['navigation'];
}>;
};

type ItemComponent = React.ComponentType<ItemComponentProps>;

interface ExampleNode {
label: string;
Expand Down Expand Up @@ -250,10 +252,25 @@ class ExampleGroup implements ExampleNode {
updateIfNeeded(_updated: () => void): void {}
}

const PageWrapper = (Component: ItemComponent) => (props: ItemComponentProps) =>
(
<Page label={props.label} onDismissExample={props.onDismissExample}>
<Component {...props} />
</Page>
);

function example(
Component: ItemComponent & { title: string; tags: string[]; docs: string },
Component: ItemComponent & {
title: string;
tags: string[];
docs: string;
page?: boolean;
},
) {
return new ExampleItem(Component.title, Component);
return new ExampleItem(
Component.title,
Component.page ? Component : PageWrapper(Component),
);
}

const BugReportPage =
Expand Down Expand Up @@ -312,7 +329,7 @@ const Examples = new ExampleGroup('React Native Mapbox', [
]),
new ExampleGroup('User Location', [
new ExampleItem('User Location Render Mode', UserLocationRenderMode),
new ExampleItem('User Location Updates', UserLocationUpdates),
example(UserLocationUpdates),
new ExampleItem('User Location Padding', UserLocationPadding),
new ExampleItem('Set Displacement', SetDisplacement),
]),
Expand Down
20 changes: 2 additions & 18 deletions ios/RNMBX/RNMBXCamera.swift
Original file line number Diff line number Diff line change
Expand Up @@ -287,25 +287,9 @@ class RNMBXCamera : RNMBXMapComponentBase {
}

if let locationModule = RNMBXLocationModule.shared {
var isSameProvider = false
#if !RNMBX_11
if let currentProvider = map.location.locationProvider as? AnyObject, let newProvider = locationModule.locationProvider as? AnyObject {
if currentProvider === newProvider {
isSameProvider = true
}
}
#endif
if !isSameProvider {
#if RNMBX_11
map.location.override(provider: locationModule.locationProvider)
#else
map.location.overrideLocationProvider(with: locationModule.locationProvider)
#endif
}
locationModule.override(for: map.location)
}
#if RNMBX_11
// RNMBX_11_TODO
#else
#if !RNMBX_11
map.location.locationProvider.requestWhenInUseAuthorization()
#endif
var trackingModeChanged = false
Expand Down
82 changes: 23 additions & 59 deletions ios/RNMBX/RNMBXLocationModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ let RCT_MAPBOX_USER_LOCATION_UPDATE = "MapboxUserLocationUpdate";
/// This implementation of LocationProviderDelegate is used by `LocationManager` to work around
/// the fact that the `LocationProvider` API does not allow the delegate to be set to `nil`.
internal class EmptyLocationProviderDelegate: LocationProviderDelegate {
#if RNMBX_11
func onLocationUpdateReceived(for locations: [Location]) {}
#endif

func locationProvider(_ provider: LocationProvider, didFailWithError error: Error) {}
func locationProvider(_ provider: LocationProvider, didUpdateHeading newHeading: CLHeading) {}
func locationProvider(_ provider: LocationProvider, didUpdateLocations locations: [CLLocation]) {}
Expand All @@ -51,17 +47,6 @@ protocol LocationProviderRNMBXDelegate : AnyObject {
class RNMBXAppleLocationProvider: NSObject {
private var locationProvider: CLLocationManager

#if RNMBX_11
private var observers : [LocationObserver] = []
private var privateAppleLocationProviderOptions: AppleLocationProvider.Options {
didSet {
locationProvider.distanceFilter = privateAppleLocationProviderOptions.distanceFilter
locationProvider.desiredAccuracy = privateAppleLocationProviderOptions.desiredAccuracy
locationProvider.activityType = privateAppleLocationProviderOptions.activityType
}
}
private var privateLocationProviderOptions: LocationOptions
#else
private var privateLocationProviderOptions: LocationOptions {
didSet {
locationProvider.distanceFilter = privateLocationProviderOptions.distanceFilter
Expand All @@ -70,17 +55,13 @@ class RNMBXAppleLocationProvider: NSObject {
}
}
private weak var delegate: LocationProviderDelegate?
#endif

public var headingOrientation: CLDeviceOrientation {
didSet { locationProvider.headingOrientation = headingOrientation }
}

public override init() {
locationProvider = CLLocationManager()
#if RNMBX_11
privateAppleLocationProviderOptions = AppleLocationProvider.Options()
#endif
privateLocationProviderOptions = LocationOptions()
headingOrientation = locationProvider.headingOrientation
super.init()
Expand All @@ -89,21 +70,6 @@ class RNMBXAppleLocationProvider: NSObject {
}

extension RNMBXAppleLocationProvider: LocationProvider {
#if RNMBX_11
func addLocationObserver(for observer: LocationObserver) {
observers.append(observer)
}

func removeLocationObserver(for observer: LocationObserver) {
observers.removeAll { $0 === observer }
}

func getLastObservedLocation() -> Location? {
locationProvider.location
}
#endif


public var locationProviderOptions: LocationOptions {
get { privateLocationProviderOptions }
set { privateLocationProviderOptions = newValue }
Expand Down Expand Up @@ -169,45 +135,29 @@ extension RNMBXAppleLocationProvider: LocationProvider {

extension RNMBXAppleLocationProvider: CLLocationManagerDelegate {
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
#if RNMBX_11
observers.forEach { $0.onLocationUpdateReceived(for: locations) }
#else
delegate?.locationProvider(self, didUpdateLocations: locations)
#endif
}

public func locationManager(_ manager: CLLocationManager, didUpdateHeading heading: CLHeading)
{
#if RNMBX_11

#else
delegate?.locationProvider(self, didUpdateHeading: heading)
#endif
public func locationManager(_ manager: CLLocationManager, didUpdateHeading heading: CLHeading) {
delegate?.locationProvider(self, didUpdateHeading: heading)
}

public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
#if RNMBX_11

#else
delegate?.locationProvider(self, didFailWithError: error)
#endif
}

@available(iOS 14.0, *)
@available(iOS 14.0, *)
public func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
#if RNMBX_11
#else
delegate?.locationProviderDidChangeAuthorization(self)
#endif
}

public func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
guard let calibratingDelegate = delegate as? CalibratingLocationProviderDelegate else {
return false
}

return calibratingDelegate.locationProviderShouldDisplayHeadingCalibration(self)
public func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
guard let calibratingDelegate = delegate as? CalibratingLocationProviderDelegate else {
return false
}

return calibratingDelegate.locationProviderShouldDisplayHeadingCalibration(self)
}
}

internal protocol CalibratingLocationProviderDelegate: LocationProviderDelegate {
Expand Down Expand Up @@ -593,6 +543,20 @@ class RNMBXLocationModule: RCTEventEmitter, LocationProviderRNMBXDelegate {
}
}

func override(for locationManager: LocationManager) {
if let locationModule = RNMBXLocationModule.shared {
var isSameProvider = false
if let currentProvider = locationManager.locationProvider as? AnyObject, let newProvider = locationModule.locationProvider as? AnyObject {
if currentProvider === newProvider {
isSameProvider = true
}
}
if !isSameProvider {
locationManager.overrideLocationProvider(with: locationModule.locationProvider)
}
}
}

// MARK: - location event throttle
@objc
func setLocationEventThrottle(_ throttleValue:NSNumber) {
Expand Down
Loading

0 comments on commit 55fa797

Please sign in to comment.