@maplibre/maplibre-react-native 10.0.0-alpha.6 → 10.0.0-alpha.8
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/.eslintrc.js +3 -1
- package/.yarn/sdks/eslint/bin/eslint.js +8 -1
- package/.yarn/sdks/eslint/lib/api.js +8 -1
- package/.yarn/sdks/eslint/lib/unsupported-api.js +8 -1
- package/.yarn/sdks/prettier/bin/prettier.cjs +8 -1
- package/.yarn/sdks/prettier/index.cjs +8 -1
- package/.yarn/sdks/typescript/bin/tsc +8 -1
- package/.yarn/sdks/typescript/bin/tsserver +8 -1
- package/.yarn/sdks/typescript/lib/tsc.js +8 -1
- package/.yarn/sdks/typescript/lib/tsserver.js +20 -6
- package/.yarn/sdks/typescript/lib/tsserverlibrary.js +20 -6
- package/.yarn/sdks/typescript/lib/typescript.js +8 -1
- package/CHANGELOG.md +7 -0
- package/CONTRIBUTING.md +10 -9
- package/android/build.gradle +1 -1
- package/android/rctmln/build.gradle +5 -5
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/annotation/MarkerView.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/annotation/MarkerViewManager.java +6 -6
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/annotation/RCTMLNMarkerView.java +5 -5
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/annotation/RCTMLNPointAnnotation.java +9 -8
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/camera/CameraStop.java +14 -12
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/camera/CameraUpdateItem.java +10 -10
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/camera/CameraUpdateQueue.java +1 -1
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/camera/RCTMLNCamera.java +26 -26
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/camera/RCTMLNCameraManager.java +1 -1
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/images/RCTMLNImages.java +12 -12
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/location/LocationComponentManager.java +9 -9
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/location/RCTMLNNativeUserLocation.java +7 -7
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/location/RCTMLNNativeUserLocationManager.java +1 -1
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/LayerSourceInfo.java +9 -9
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/RCTMLNAndroidTextureMapView.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/RCTMLNAndroidTextureMapViewManager.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/RCTMLNMapView.java +43 -43
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/mapview/RCTMLNMapViewManager.java +6 -6
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/RCTMLNStyle.java +3 -3
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/RCTMLNStyleFactory.java +14 -14
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/RCTMLNStyleFunctionParser.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/RCTMLNStyleValue.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTLayer.java +8 -8
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNBackgroundLayer.java +1 -1
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNCircleLayer.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNFillExtrusionLayer.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNFillLayer.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNHeatmapLayer.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNLineLayer.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNRasterLayer.java +1 -1
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/layers/RCTMLNSymbolLayer.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/light/RCTMLNLight.java +6 -6
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNImageSource.java +3 -3
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNImageSourceManager.java +1 -1
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNRasterSource.java +3 -3
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNShapeSource.java +9 -9
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNShapeSourceManager.java +1 -1
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNTileSource.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTMLNVectorSource.java +4 -4
- package/android/rctmln/src/main/java/com/maplibre/rctmln/components/styles/sources/RCTSource.java +7 -7
- package/android/rctmln/src/main/java/com/maplibre/rctmln/events/FeatureClickEvent.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/events/MapClickEvent.java +1 -1
- package/android/rctmln/src/main/java/com/maplibre/rctmln/events/PointAnnotationClickEvent.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/events/PointAnnotationDragEvent.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/location/LocationManager.java +6 -6
- package/android/rctmln/src/main/java/com/maplibre/rctmln/location/UserLocation.java +1 -1
- package/android/rctmln/src/main/java/com/maplibre/rctmln/location/UserTrackingMode.java +3 -3
- package/android/rctmln/src/main/java/com/maplibre/rctmln/modules/RCTMLNLocationModule.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/modules/RCTMLNLogging.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/modules/RCTMLNModule.java +8 -8
- package/android/rctmln/src/main/java/com/maplibre/rctmln/modules/RCTMLNOfflineModule.java +11 -11
- package/android/rctmln/src/main/java/com/maplibre/rctmln/modules/RCTMLNSnapshotModule.java +7 -7
- package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/ClusterPropertyEntry.java +1 -1
- package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/DownloadMapImageTask.java +5 -5
- package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/ExpressionParser.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/GeoJSONUtils.java +13 -13
- package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/GeoViewport.java +3 -3
- package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/SimpleEventCallback.java +2 -2
- package/android/rctmln/src/main/java/com/maplibre/rctmln/utils/SphericalMercator.java +1 -1
- package/docs/Camera.md +3 -3
- package/docs/MapView.md +9 -33
- package/docs/UserLocation.md +10 -2
- package/docs/docs.json +16 -31
- package/javascript/Maplibre.ts +5 -1
- package/javascript/components/BackgroundLayer.tsx +27 -20
- package/javascript/components/Callout.tsx +40 -40
- package/javascript/components/Camera.tsx +421 -478
- package/javascript/components/CircleLayer.tsx +29 -22
- package/javascript/components/FillExtrusionLayer.tsx +23 -23
- package/javascript/components/FillLayer.tsx +22 -19
- package/javascript/components/HeatmapLayer.tsx +21 -19
- package/javascript/components/ImageSource.tsx +25 -32
- package/javascript/components/Images.tsx +36 -35
- package/javascript/components/Light.tsx +20 -47
- package/javascript/components/LineLayer.tsx +23 -20
- package/javascript/components/MapView.tsx +604 -554
- package/javascript/components/MarkerView.tsx +23 -38
- package/javascript/components/NativeUserLocation.tsx +3 -5
- package/javascript/components/PointAnnotation.tsx +111 -87
- package/javascript/components/RasterLayer.tsx +21 -18
- package/javascript/components/RasterSource.tsx +39 -42
- package/javascript/components/ShapeSource.tsx +287 -239
- package/javascript/components/Style.tsx +1 -1
- package/javascript/components/SymbolLayer.tsx +34 -28
- package/javascript/components/UserLocation.tsx +164 -151
- package/javascript/components/VectorSource.tsx +128 -117
- package/javascript/components/annotations/Annotation.tsx +105 -79
- package/javascript/{components/AbstractLayer.tsx → hooks/useAbstractLayer.ts} +54 -37
- package/javascript/hooks/useAbstractSource.ts +34 -0
- package/javascript/hooks/useNativeBridge.ts +125 -0
- package/javascript/hooks/useNativeRef.ts +13 -0
- package/javascript/hooks/useOnce.ts +12 -0
- package/javascript/utils/Logger.ts +3 -3
- package/package.json +2 -1
- package/scripts/templates/RCTMLNStyleFactory.java.ejs +14 -14
- package/javascript/components/AbstractSource.tsx +0 -27
- package/javascript/components/NativeBridgeComponent.tsx +0 -117
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {type SymbolLayerStyleProps} from '../utils/MaplibreStyles';
|
|
2
2
|
import BaseProps from '../types/BaseProps';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import useAbstractLayer, {
|
|
4
|
+
BaseLayerProps,
|
|
5
|
+
NativeBaseProps,
|
|
6
|
+
} from '../hooks/useAbstractLayer';
|
|
5
7
|
|
|
6
8
|
import React, {ReactElement} from 'react';
|
|
7
9
|
import {View, NativeModules, requireNativeComponent} from 'react-native';
|
|
@@ -10,7 +12,7 @@ const MapLibreGL = NativeModules.MLNModule;
|
|
|
10
12
|
|
|
11
13
|
export const NATIVE_MODULE_NAME = 'RCTMLNSymbolLayer';
|
|
12
14
|
|
|
13
|
-
interface SymbolLayerProps extends BaseProps, BaseLayerProps {
|
|
15
|
+
export interface SymbolLayerProps extends BaseProps, BaseLayerProps {
|
|
14
16
|
/**
|
|
15
17
|
* Customizable style attributes
|
|
16
18
|
*/
|
|
@@ -27,46 +29,50 @@ interface NativeProps extends Omit<SymbolLayerProps, 'style'>, NativeBaseProps {
|
|
|
27
29
|
snapshot: boolean;
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
const RCTMLNSymbolLayer =
|
|
33
|
+
requireNativeComponent<NativeProps>(NATIVE_MODULE_NAME);
|
|
34
|
+
|
|
30
35
|
/**
|
|
31
36
|
* SymbolLayer is a style layer that renders icon and text labels at points or along lines on the map.
|
|
32
37
|
*/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
const SymbolLayer: React.FC<SymbolLayerProps> = ({
|
|
39
|
+
sourceID = MapLibreGL.StyleSource.DefaultSourceID,
|
|
40
|
+
...props
|
|
41
|
+
}: SymbolLayerProps) => {
|
|
42
|
+
const {baseProps, setNativeLayer} = useAbstractLayer<
|
|
43
|
+
SymbolLayerProps,
|
|
44
|
+
NativeBaseProps
|
|
45
|
+
>({
|
|
46
|
+
...props,
|
|
47
|
+
sourceID,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const _shouldSnapshot = (): boolean => {
|
|
39
51
|
let isSnapshot = false;
|
|
40
52
|
|
|
41
|
-
if (React.Children.count(
|
|
53
|
+
if (React.Children.count(props.children) <= 0) {
|
|
42
54
|
return isSnapshot;
|
|
43
55
|
}
|
|
44
56
|
|
|
45
|
-
React.Children.forEach(
|
|
57
|
+
React.Children.forEach(props.children, child => {
|
|
46
58
|
if (child?.type === View) {
|
|
47
59
|
isSnapshot = true;
|
|
48
60
|
}
|
|
49
61
|
});
|
|
50
62
|
|
|
51
63
|
return isSnapshot;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
render(): ReactElement {
|
|
55
|
-
const props = {
|
|
56
|
-
...this.baseProps,
|
|
57
|
-
snapshot: this._shouldSnapshot(),
|
|
58
|
-
sourceLayerID: this.props.sourceLayerID,
|
|
59
|
-
};
|
|
64
|
+
};
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
66
|
+
const updatedProps = {
|
|
67
|
+
...baseProps,
|
|
68
|
+
snapshot: _shouldSnapshot(),
|
|
69
|
+
};
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
return (
|
|
72
|
+
<RCTMLNSymbolLayer ref={setNativeLayer} {...updatedProps}>
|
|
73
|
+
{props.children}
|
|
74
|
+
</RCTMLNSymbolLayer>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
71
77
|
|
|
72
78
|
export default SymbolLayer;
|
|
@@ -6,7 +6,7 @@ import CircleLayer from './CircleLayer';
|
|
|
6
6
|
import HeadingIndicator from './HeadingIndicator';
|
|
7
7
|
import NativeUserLocation from './NativeUserLocation';
|
|
8
8
|
|
|
9
|
-
import React, {ReactElement} from 'react';
|
|
9
|
+
import React, {ReactElement, useEffect, useImperativeHandle} from 'react';
|
|
10
10
|
|
|
11
11
|
const mapboxBlue = 'rgba(51, 181, 229, 100)';
|
|
12
12
|
|
|
@@ -113,164 +113,177 @@ export enum UserLocationRenderMode {
|
|
|
113
113
|
Normal = 'normal',
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
animated: true,
|
|
122
|
-
visible: true,
|
|
123
|
-
showsUserHeadingIndicator: false,
|
|
124
|
-
minDisplacement: 0,
|
|
125
|
-
renderMode: 'normal',
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
constructor(props: UserLocationProps) {
|
|
129
|
-
super(props);
|
|
130
|
-
|
|
131
|
-
this.state = {
|
|
132
|
-
shouldShowUserLocation: false,
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
this._onLocationUpdate = this._onLocationUpdate.bind(this);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// required as #setLocationManager attempts to setState
|
|
139
|
-
// after component unmount
|
|
140
|
-
_isMounted: boolean | null = null;
|
|
141
|
-
|
|
142
|
-
renderMode: UserLocationRenderMode | undefined;
|
|
143
|
-
locationManagerRunning = false;
|
|
144
|
-
|
|
145
|
-
async componentDidMount(): Promise<void> {
|
|
146
|
-
this._isMounted = true;
|
|
116
|
+
export interface UserLocationRef {
|
|
117
|
+
setLocationManager: (props: {running: boolean}) => Promise<void>;
|
|
118
|
+
needsLocationManagerRunning: () => boolean;
|
|
119
|
+
_onLocationUpdate: (location: Location | null) => void;
|
|
120
|
+
}
|
|
147
121
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
122
|
+
const UserLocation = React.memo(
|
|
123
|
+
React.forwardRef<UserLocationRef, UserLocationProps>(
|
|
124
|
+
(
|
|
125
|
+
{
|
|
126
|
+
animated = true,
|
|
127
|
+
visible = true,
|
|
128
|
+
showsUserHeadingIndicator = false,
|
|
129
|
+
minDisplacement = 0,
|
|
130
|
+
renderMode = 'normal',
|
|
131
|
+
androidRenderMode,
|
|
132
|
+
children,
|
|
133
|
+
onUpdate,
|
|
134
|
+
onPress,
|
|
135
|
+
}: UserLocationProps,
|
|
136
|
+
ref,
|
|
137
|
+
) => {
|
|
138
|
+
const _isMounted = React.useRef<boolean | null>(null);
|
|
139
|
+
const locationManagerRunning = React.useRef<boolean>(false);
|
|
140
|
+
|
|
141
|
+
const [userLocationState, setUserLocationState] =
|
|
142
|
+
React.useState<UserLocationState>({
|
|
143
|
+
shouldShowUserLocation: false,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
useImperativeHandle(
|
|
147
|
+
ref,
|
|
148
|
+
(): UserLocationRef => ({
|
|
149
|
+
/**
|
|
150
|
+
* Whether to start or stop listening to the locationManager
|
|
151
|
+
*
|
|
152
|
+
* Notice, that listening will start automatically when
|
|
153
|
+
* either `onUpdate` or `visible` are set
|
|
154
|
+
*
|
|
155
|
+
* @async
|
|
156
|
+
* @param {Object} running - Object with key `running` and `boolean` value
|
|
157
|
+
* @return {Promise<void>}
|
|
158
|
+
*/
|
|
159
|
+
setLocationManager,
|
|
160
|
+
/**
|
|
161
|
+
*
|
|
162
|
+
* If locationManager should be running
|
|
163
|
+
*
|
|
164
|
+
* @return {boolean}
|
|
165
|
+
*/
|
|
166
|
+
needsLocationManagerRunning,
|
|
167
|
+
_onLocationUpdate,
|
|
168
|
+
}),
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
_isMounted.current = true;
|
|
173
|
+
|
|
174
|
+
setLocationManager({
|
|
175
|
+
running: needsLocationManagerRunning(),
|
|
176
|
+
}).then(() => {
|
|
177
|
+
if (renderMode === UserLocationRenderMode.Native) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
locationManager.setMinDisplacement(minDisplacement ?? 0);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
return (): void => {
|
|
185
|
+
_isMounted.current = false;
|
|
186
|
+
setLocationManager({running: false});
|
|
187
|
+
};
|
|
188
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
189
|
+
}, []);
|
|
190
|
+
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
locationManager.setMinDisplacement(minDisplacement ?? 0);
|
|
193
|
+
}, [minDisplacement]);
|
|
194
|
+
|
|
195
|
+
useEffect(() => {
|
|
196
|
+
if (!_isMounted.current) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
setLocationManager({
|
|
201
|
+
running: needsLocationManagerRunning(),
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
async function setLocationManager({
|
|
206
|
+
running,
|
|
207
|
+
}: {
|
|
208
|
+
running: boolean;
|
|
209
|
+
}): Promise<void> {
|
|
210
|
+
if (locationManagerRunning.current !== running) {
|
|
211
|
+
locationManagerRunning.current = running;
|
|
212
|
+
|
|
213
|
+
if (running) {
|
|
214
|
+
locationManager.addListener(_onLocationUpdate);
|
|
215
|
+
const location = await locationManager.getLastKnownLocation();
|
|
216
|
+
_onLocationUpdate(location);
|
|
217
|
+
} else {
|
|
218
|
+
locationManager.removeListener(_onLocationUpdate);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
151
222
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
223
|
+
function needsLocationManagerRunning(): boolean {
|
|
224
|
+
return !!(
|
|
225
|
+
!!onUpdate ||
|
|
226
|
+
(renderMode === UserLocationRenderMode.Normal && visible)
|
|
227
|
+
);
|
|
228
|
+
}
|
|
155
229
|
|
|
156
|
-
|
|
157
|
-
|
|
230
|
+
function _onLocationUpdate(location: Location | null): void {
|
|
231
|
+
if (!_isMounted.current || !location) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let coordinates;
|
|
236
|
+
let heading;
|
|
237
|
+
|
|
238
|
+
if (location && location.coords) {
|
|
239
|
+
const {longitude, latitude} = location.coords;
|
|
240
|
+
heading = location.coords.heading;
|
|
241
|
+
coordinates = [longitude, latitude];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
setUserLocationState({
|
|
245
|
+
...userLocationState,
|
|
246
|
+
coordinates,
|
|
247
|
+
heading,
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
if (onUpdate) {
|
|
251
|
+
onUpdate(location);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
158
254
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
});
|
|
255
|
+
if (!visible) {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
163
258
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
259
|
+
if (renderMode === UserLocationRenderMode.Native) {
|
|
260
|
+
const props = {
|
|
261
|
+
androidRenderMode,
|
|
262
|
+
iosShowsUserHeadingIndicator: showsUserHeadingIndicator,
|
|
263
|
+
};
|
|
168
264
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
await this.setLocationManager({running: false});
|
|
172
|
-
}
|
|
265
|
+
return <NativeUserLocation {...props} />;
|
|
266
|
+
}
|
|
173
267
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
*
|
|
177
|
-
* Notice, that listening will start automatically when
|
|
178
|
-
* either `onUpdate` or `visible` are set
|
|
179
|
-
*
|
|
180
|
-
* @async
|
|
181
|
-
* @param {Object} running - Object with key `running` and `boolean` value
|
|
182
|
-
* @return {Promise<void>}
|
|
183
|
-
*/
|
|
184
|
-
async setLocationManager({running}: {running: boolean}): Promise<void> {
|
|
185
|
-
if (this.locationManagerRunning !== running) {
|
|
186
|
-
this.locationManagerRunning = running;
|
|
187
|
-
if (running) {
|
|
188
|
-
locationManager.addListener(this._onLocationUpdate);
|
|
189
|
-
const location = await locationManager.getLastKnownLocation();
|
|
190
|
-
this._onLocationUpdate(location);
|
|
191
|
-
} else {
|
|
192
|
-
locationManager.removeListener(this._onLocationUpdate);
|
|
268
|
+
if (!userLocationState.coordinates) {
|
|
269
|
+
return null;
|
|
193
270
|
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
271
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
let coordinates;
|
|
216
|
-
let heading;
|
|
217
|
-
|
|
218
|
-
if (location && location.coords) {
|
|
219
|
-
const {longitude, latitude} = location.coords;
|
|
220
|
-
heading = location.coords.heading;
|
|
221
|
-
coordinates = [longitude, latitude];
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
this.setState({
|
|
225
|
-
coordinates,
|
|
226
|
-
heading,
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
if (this.props.onUpdate) {
|
|
230
|
-
this.props.onUpdate(location);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
_renderNative(): ReactElement {
|
|
235
|
-
const {androidRenderMode, showsUserHeadingIndicator} = this.props;
|
|
236
|
-
|
|
237
|
-
const props = {
|
|
238
|
-
androidRenderMode,
|
|
239
|
-
iosShowsUserHeadingIndicator: showsUserHeadingIndicator,
|
|
240
|
-
};
|
|
241
|
-
return <NativeUserLocation {...props} />;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
render(): ReactElement | null {
|
|
245
|
-
const {heading, coordinates} = this.state;
|
|
246
|
-
const {children, visible, showsUserHeadingIndicator, onPress, animated} =
|
|
247
|
-
this.props;
|
|
248
|
-
|
|
249
|
-
if (!visible) {
|
|
250
|
-
return null;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
if (this.props.renderMode === UserLocationRenderMode.Native) {
|
|
254
|
-
return this._renderNative();
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if (!coordinates) {
|
|
258
|
-
return null;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return (
|
|
262
|
-
<Annotation
|
|
263
|
-
animated={animated}
|
|
264
|
-
id="mapboxUserLocation"
|
|
265
|
-
onPress={onPress}
|
|
266
|
-
coordinates={coordinates}
|
|
267
|
-
style={{
|
|
268
|
-
iconRotate: heading,
|
|
269
|
-
}}>
|
|
270
|
-
{children || normalIcon(showsUserHeadingIndicator, heading)}
|
|
271
|
-
</Annotation>
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
272
|
+
return (
|
|
273
|
+
<Annotation
|
|
274
|
+
animated={animated}
|
|
275
|
+
id="mapboxUserLocation"
|
|
276
|
+
onPress={onPress}
|
|
277
|
+
coordinates={userLocationState.coordinates}
|
|
278
|
+
style={{
|
|
279
|
+
iconRotate: userLocationState.heading,
|
|
280
|
+
}}>
|
|
281
|
+
{children ||
|
|
282
|
+
normalIcon(showsUserHeadingIndicator, userLocationState.heading)}
|
|
283
|
+
</Annotation>
|
|
284
|
+
);
|
|
285
|
+
},
|
|
286
|
+
),
|
|
287
|
+
);
|
|
275
288
|
|
|
276
289
|
export default UserLocation;
|
|
@@ -4,13 +4,11 @@ import {getFilter} from '../utils/filterUtils';
|
|
|
4
4
|
import {copyPropertiesAsDeprecated} from '../utils/deprecation';
|
|
5
5
|
import BaseProps from '../types/BaseProps';
|
|
6
6
|
import OnPressEvent from '../types/OnPressEvent';
|
|
7
|
+
import useAbstractSource from '../hooks/useAbstractSource';
|
|
8
|
+
import useNativeBridge from '../hooks/useNativeBridge';
|
|
7
9
|
|
|
8
|
-
import
|
|
9
|
-
import NativeBridgeComponent from './NativeBridgeComponent';
|
|
10
|
-
|
|
11
|
-
import React, {Component, ReactNode} from 'react';
|
|
10
|
+
import React, {memo, useImperativeHandle} from 'react';
|
|
12
11
|
import {
|
|
13
|
-
NativeMethods,
|
|
14
12
|
NativeModules,
|
|
15
13
|
NativeSyntheticEvent,
|
|
16
14
|
requireNativeComponent,
|
|
@@ -85,123 +83,136 @@ interface VectorSourceProps extends BaseProps {
|
|
|
85
83
|
|
|
86
84
|
type NativeProps = VectorSourceProps;
|
|
87
85
|
|
|
86
|
+
const RCTMLNVectorSource =
|
|
87
|
+
requireNativeComponent<VectorSourceProps>(NATIVE_MODULE_NAME);
|
|
88
|
+
|
|
88
89
|
/**
|
|
89
90
|
* VectorSource is a map content source that supplies tiled vector data in Mapbox Vector Tile format to be shown on the map.
|
|
90
91
|
* The location of and metadata about the tiles are defined either by an option dictionary or by an external file that conforms to the TileJSON specification.
|
|
91
92
|
*/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
) {
|
|
96
|
-
static defaultProps = {
|
|
97
|
-
id: MapLibreGL.StyleSource.DefaultSourceID,
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
constructor(props: VectorSourceProps) {
|
|
101
|
-
super(props);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
_setNativeRef(
|
|
105
|
-
nativeRef: (Component<NativeProps> & Readonly<NativeMethods>) | null,
|
|
106
|
-
): void {
|
|
107
|
-
if (nativeRef) {
|
|
108
|
-
this.setNativeRef(nativeRef);
|
|
109
|
-
super._runPendingNativeCommands(nativeRef);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Returns all features that match the query parameters regardless of whether or not the feature is
|
|
115
|
-
* currently rendered on the map. The domain of the query includes all currently-loaded vector tiles
|
|
116
|
-
* and GeoJSON source tiles. This function does not check tiles outside of the visible viewport.
|
|
117
|
-
*
|
|
118
|
-
* @example
|
|
119
|
-
* vectorSource.features(['id1', 'id2'])
|
|
120
|
-
*
|
|
121
|
-
* @param {Array=} layerIDs - A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array.
|
|
122
|
-
* @param {Array=} filter - an optional filter statement to filter the returned Features.
|
|
123
|
-
* @return {GeoJSON.FeatureCollection}
|
|
124
|
-
*/
|
|
125
|
-
async features(
|
|
126
|
-
layerIDs = [],
|
|
127
|
-
filter?: FilterExpression,
|
|
128
|
-
): Promise<GeoJSON.FeatureCollection> {
|
|
129
|
-
if (!this._nativeRef) {
|
|
130
|
-
return featureCollection([]);
|
|
131
|
-
}
|
|
132
|
-
const res: {data: string | GeoJSON.FeatureCollection} =
|
|
133
|
-
await this._runNativeCommand('features', this._nativeRef, [
|
|
134
|
-
[[layerIDs, getFilter(filter)]],
|
|
135
|
-
]);
|
|
136
|
-
|
|
137
|
-
if (isAndroid()) {
|
|
138
|
-
return JSON.parse(res?.data as string);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return res.data as GeoJSON.FeatureCollection;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
onPress(event: NativeSyntheticEvent<{payload: OnPressEvent}>): void {
|
|
145
|
-
const {onPress} = this.props;
|
|
146
|
-
|
|
147
|
-
if (!onPress) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
const {
|
|
151
|
-
nativeEvent: {
|
|
152
|
-
payload: {features, coordinates, point},
|
|
153
|
-
},
|
|
154
|
-
} = event;
|
|
155
|
-
let newEvent = {
|
|
156
|
-
features,
|
|
157
|
-
coordinates,
|
|
158
|
-
point,
|
|
159
|
-
};
|
|
160
|
-
newEvent = copyPropertiesAsDeprecated(
|
|
161
|
-
event,
|
|
162
|
-
newEvent,
|
|
163
|
-
(key: string) => {
|
|
164
|
-
console.warn(
|
|
165
|
-
`event.${key} is deprecated on VectorSource#onPress, please use event.features`,
|
|
166
|
-
);
|
|
167
|
-
},
|
|
93
|
+
const VectorSource = memo(
|
|
94
|
+
React.forwardRef(
|
|
95
|
+
(
|
|
168
96
|
{
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
97
|
+
id = MapLibreGL.StyleSource.DefaultSourceID,
|
|
98
|
+
...props
|
|
99
|
+
}: VectorSourceProps,
|
|
100
|
+
ref,
|
|
101
|
+
) => {
|
|
102
|
+
// * exposes the methods of the function component so we don't break projects that depend on calling this methods
|
|
103
|
+
useImperativeHandle(ref, () => ({
|
|
104
|
+
/**
|
|
105
|
+
* Returns all features that match the query parameters regardless of whether or not the feature is
|
|
106
|
+
* currently rendered on the map. The domain of the query includes all currently-loaded vector tiles
|
|
107
|
+
* and GeoJSON source tiles. This function does not check tiles outside of the visible viewport.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* vectorSource.features(['id1', 'id2'])
|
|
111
|
+
*
|
|
112
|
+
* @param {Array=} layerIDs - A set of strings that correspond to the names of layers defined in the current style. Only the features contained in these layers are included in the returned array.
|
|
113
|
+
* @param {Array=} filter - an optional filter statement to filter the returned Features.
|
|
114
|
+
* @return {GeoJSON.FeatureCollection}
|
|
115
|
+
*/
|
|
116
|
+
features,
|
|
117
|
+
onPress,
|
|
118
|
+
}));
|
|
119
|
+
|
|
120
|
+
const {
|
|
121
|
+
_runNativeCommand,
|
|
122
|
+
// _runPendingNativeCommands,
|
|
123
|
+
_onAndroidCallback,
|
|
124
|
+
} = useNativeBridge(NATIVE_MODULE_NAME);
|
|
125
|
+
const {setNativeRef, _nativeRef} = useAbstractSource<NativeProps>();
|
|
126
|
+
|
|
127
|
+
// const _setNativeRef = (
|
|
128
|
+
// nativeRef: (Component<NativeProps> & Readonly<NativeMethods>) | null,
|
|
129
|
+
// ): void => {
|
|
130
|
+
// if (nativeRef) {
|
|
131
|
+
// setNativeRef(nativeRef);
|
|
132
|
+
// _runPendingNativeCommands(nativeRef);
|
|
133
|
+
// }
|
|
134
|
+
// };
|
|
135
|
+
|
|
136
|
+
const features = async (
|
|
137
|
+
layerIDs = [],
|
|
138
|
+
filter?: FilterExpression,
|
|
139
|
+
): Promise<GeoJSON.FeatureCollection> => {
|
|
140
|
+
if (!_nativeRef) {
|
|
141
|
+
return featureCollection([]);
|
|
142
|
+
}
|
|
143
|
+
const res: {data: string | GeoJSON.FeatureCollection} =
|
|
144
|
+
await _runNativeCommand('features', _nativeRef, [
|
|
145
|
+
[[layerIDs, getFilter(filter)]],
|
|
146
|
+
]);
|
|
147
|
+
|
|
148
|
+
if (isAndroid()) {
|
|
149
|
+
return JSON.parse(res?.data as string);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return res.data as GeoJSON.FeatureCollection;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const onPress = (
|
|
156
|
+
event: NativeSyntheticEvent<{payload: OnPressEvent}>,
|
|
157
|
+
): void => {
|
|
158
|
+
const {onPress} = props;
|
|
159
|
+
|
|
160
|
+
if (!onPress) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const {
|
|
164
|
+
nativeEvent: {
|
|
165
|
+
payload: {features, coordinates, point},
|
|
166
|
+
},
|
|
167
|
+
} = event;
|
|
168
|
+
let newEvent = {
|
|
169
|
+
features,
|
|
170
|
+
coordinates,
|
|
171
|
+
point,
|
|
172
|
+
};
|
|
173
|
+
newEvent = copyPropertiesAsDeprecated(
|
|
174
|
+
event,
|
|
175
|
+
newEvent,
|
|
176
|
+
(key: string) => {
|
|
177
|
+
console.warn(
|
|
178
|
+
`event.${key} is deprecated on VectorSource#onPress, please use event.features`,
|
|
179
|
+
);
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
nativeEvent: (origNativeEvent: OnPressEvent) => ({
|
|
183
|
+
...origNativeEvent,
|
|
184
|
+
payload: features[0],
|
|
185
|
+
}),
|
|
186
|
+
},
|
|
187
|
+
);
|
|
203
188
|
|
|
204
|
-
|
|
205
|
-
|
|
189
|
+
onPress(newEvent);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const allProps = {
|
|
193
|
+
id,
|
|
194
|
+
url: props.url,
|
|
195
|
+
tileUrlTemplates: props.tileUrlTemplates,
|
|
196
|
+
minZoomLevel: props.minZoomLevel,
|
|
197
|
+
maxZoomLevel: props.maxZoomLevel,
|
|
198
|
+
tms: props.tms,
|
|
199
|
+
attribution: props.attribution,
|
|
200
|
+
hitbox: props.hitbox,
|
|
201
|
+
hasPressListener: isFunction(props.onPress),
|
|
202
|
+
onMapboxVectorSourcePress: onPress,
|
|
203
|
+
onPress: undefined,
|
|
204
|
+
onAndroidCallback: isAndroid() ? _onAndroidCallback : undefined,
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
<RCTMLNVectorSource ref={setNativeRef} {...allProps}>
|
|
209
|
+
{cloneReactChildrenWithProps(props.children, {
|
|
210
|
+
sourceID: id,
|
|
211
|
+
})}
|
|
212
|
+
</RCTMLNVectorSource>
|
|
213
|
+
);
|
|
214
|
+
},
|
|
215
|
+
),
|
|
216
|
+
);
|
|
206
217
|
|
|
207
218
|
export default VectorSource;
|