@nativescript-community/ui-mapbox 6.2.9 → 6.2.13

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +199 -99
  3. package/{mapbox.common.d.ts → common.d.ts} +20 -3
  4. package/{mapbox.common.js → common.js} +18 -1
  5. package/{filter/filter-parser.android.d.ts → expression/expression-parser.android.d.ts} +1 -1
  6. package/{filter/filter-parser.android.js → expression/expression-parser.android.js} +2 -2
  7. package/expression/expression-parser.d.ts +4 -0
  8. package/{filter/filter-parser.ios.d.ts → expression/expression-parser.ios.d.ts} +1 -1
  9. package/{filter/filter-parser.ios.js → expression/expression-parser.ios.js} +2 -2
  10. package/{mapbox.android.d.ts → index.android.d.ts} +5 -14
  11. package/{mapbox.android.js → index.android.js} +142 -66
  12. package/index.d.ts +98 -6
  13. package/{mapbox.ios.d.ts → index.ios.d.ts} +3 -30
  14. package/{mapbox.ios.js → index.ios.js} +1300 -1250
  15. package/layers/layer-factory.android.d.ts +14 -1
  16. package/layers/layer-factory.android.js +33 -2
  17. package/layers/layer-factory.d.ts +15 -1
  18. package/layers/layer-factory.ios.d.ts +14 -1
  19. package/layers/layer-factory.ios.js +42 -2
  20. package/layers/parser/property-parser.android.d.ts +1 -0
  21. package/layers/parser/property-parser.android.js +25 -0
  22. package/layers/parser/property-parser.d.ts +4 -0
  23. package/layers/parser/property-parser.ios.d.ts +1 -0
  24. package/layers/parser/property-parser.ios.js +21 -0
  25. package/package.json +55 -49
  26. package/platforms/android/include.gradle +4 -1
  27. package/platforms/android/ui_mapbox.aar +0 -0
  28. package/platforms/ios/Podfile +2 -2
  29. package/typings/Mapbox.ios.d.ts +2 -0
  30. package/LICENSE +0 -21
@@ -1,10 +1,416 @@
1
- import { Color, File, ImageSource, Trace, knownFolders, path } from '@nativescript/core';
2
- import { CLog, CLogTypes, MapStyle, MapboxCommon, MapboxTraceCategory, MapboxViewBase, telemetryProperty } from './mapbox.common';
3
- import { iOSNativeHelper } from '@nativescript/core/utils';
4
- import { getImage } from '@nativescript/core/http';
5
- import { LayerFactory } from './layers/layer-factory';
6
- import { FilterParser } from './filter/filter-parser.ios';
7
- export { MapboxTraceCategory, MapStyle };
1
+ import { Color, File, Http, ImageSource, Trace, Utils, knownFolders, path } from '@nativescript/core';
2
+ import { CLog, CLogTypes, MapStyle, MapboxCommon, MapboxViewBase, telemetryProperty } from './common';
3
+ import { Layer, LayerFactory } from './layers/layer-factory';
4
+ import { ExpressionParser } from './expression/expression-parser';
5
+ var MGLMapViewDelegateImpl = /** @class */ (function (_super) {
6
+ __extends(MGLMapViewDelegateImpl, _super);
7
+ function MGLMapViewDelegateImpl() {
8
+ return _super !== null && _super.apply(this, arguments) || this;
9
+ }
10
+ MGLMapViewDelegateImpl.new = function () {
11
+ return _super.new.call(this);
12
+ };
13
+ /**
14
+ * initialize with the mapReady callback
15
+ */
16
+ MGLMapViewDelegateImpl.prototype.initWithCallback = function (mapLoadedCallback) {
17
+ if (Trace.isEnabled()) {
18
+ CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::initWithCallback()');
19
+ }
20
+ this.mapLoadedCallback = mapLoadedCallback;
21
+ return this;
22
+ };
23
+ /**
24
+ * set a reference to the mapboxAPI instance
25
+ */
26
+ MGLMapViewDelegateImpl.prototype.setMapboxApi = function (api) {
27
+ this.mapboxApi = api;
28
+ };
29
+ /**
30
+ * set the user location click listener callback
31
+ */
32
+ MGLMapViewDelegateImpl.prototype.setUserLocationClickListener = function (callback) {
33
+ this.userLocationClickListener = callback;
34
+ };
35
+ /**
36
+ * set the user location click listener callback
37
+ */
38
+ MGLMapViewDelegateImpl.prototype.setUserLocationChangedistener = function (callback) {
39
+ this.userLocationChangedListener = callback;
40
+ };
41
+ /**
42
+ * set user location marker modes
43
+ */
44
+ MGLMapViewDelegateImpl.prototype.changeUserLocationRenderMode = function (userLocationRenderMode) {
45
+ this.userLocationAnnotationView.changeUserLocationRenderMode(userLocationRenderMode);
46
+ };
47
+ /**
48
+ * set the camera changd listener callback
49
+ */
50
+ MGLMapViewDelegateImpl.prototype.setCameraChangedListener = function (callback) {
51
+ this.cameraChangedListener = callback;
52
+ };
53
+ /**
54
+ * set the camera idled listener callback
55
+ */
56
+ MGLMapViewDelegateImpl.prototype.setCameraIdledListener = function (callback) {
57
+ this.cameraIdledListener = callback;
58
+ };
59
+ /**
60
+ * set style loaded callback.
61
+ *
62
+ * set an optional callback to be invoked when a style set with
63
+ * setMapStyle() is finished loading
64
+ *
65
+ * @param {function} callback function with loaded style as parameter.
66
+ *
67
+ * @see Mapbox:setMapStyle()
68
+ */
69
+ MGLMapViewDelegateImpl.prototype.setStyleLoadedCallback = function (callback) {
70
+ this.styleLoadedCallback = callback;
71
+ };
72
+ /**
73
+ * map ready callback
74
+ */
75
+ MGLMapViewDelegateImpl.prototype.mapViewDidFinishLoadingMap = function (mapView) {
76
+ if (Trace.isEnabled()) {
77
+ CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingMap(): top');
78
+ }
79
+ if (this.mapLoadedCallback !== undefined) {
80
+ this.mapLoadedCallback(mapView);
81
+ // this should be fired only once, but it's also fired when the style changes, so just remove the callback
82
+ this.mapLoadedCallback = undefined;
83
+ }
84
+ };
85
+ MGLMapViewDelegateImpl.prototype.mapViewDidFinishRenderingMapFullyRendered = function (mapView, fullyRendered) {
86
+ if (Trace.isEnabled()) {
87
+ CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishRenderingMapFullyRendered(): rendered is:', fullyRendered);
88
+ }
89
+ };
90
+ /**
91
+ * Callback when the style has been loaded.
92
+ *
93
+ * Based on my testing, it looks like this callback is invoked multiple times.
94
+ *
95
+ * @see Mapbox:setMapStyle()
96
+ *
97
+ * @link https://mapbox.github.io/mapbox-gl-native/macos/0.3.0/Protocols/MGLMapViewDelegate.html#/c:objc(pl)MGLMapViewDelegate(im)mapView:didFinishLoadingStyle:
98
+ */
99
+ MGLMapViewDelegateImpl.prototype.mapViewDidFinishLoadingStyle = function (mapView, style) {
100
+ if (Trace.isEnabled()) {
101
+ CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingStyle(): callback called.');
102
+ }
103
+ if (this.styleLoadedCallback !== undefined) {
104
+ this.styleLoadedCallback(mapView, style);
105
+ // to avoid multiple calls. This is only invoked from setMapStyle().
106
+ this.styleLoadedCallback = undefined;
107
+ }
108
+ };
109
+ /**
110
+ * disable the default user location callout
111
+ *
112
+ * This took forever to find. The default iOS click handler for the user location
113
+ * marker is about useless. It just displays "You Are Here". The examples do not
114
+ * show how to disable it.
115
+ */
116
+ MGLMapViewDelegateImpl.prototype.mapViewAnnotationCanShowCallout = function (mapView, annotation) {
117
+ if (annotation.isKindOfClass(MGLUserLocation.class())) {
118
+ return false;
119
+ }
120
+ else {
121
+ return true;
122
+ }
123
+ };
124
+ MGLMapViewDelegateImpl.prototype.mapViewDidFailLoadingMapWithError = function (mapView, error) {
125
+ if (Trace.isEnabled()) {
126
+ CLog(CLogTypes.info, 'mapViewDidFailLoadingMapWithError: ' + error);
127
+ }
128
+ };
129
+ MGLMapViewDelegateImpl.prototype.mapViewDidChangeUserTrackingModeAnimated = function (mapView, mode, animated) {
130
+ if (Trace.isEnabled()) {
131
+ CLog(CLogTypes.info, 'mapViewDidChangeUserTrackingModeAnimated: ' + mode);
132
+ }
133
+ };
134
+ /**
135
+ * fired when the marker icon is about to be rendered - return null for the default icon
136
+ */
137
+ MGLMapViewDelegateImpl.prototype.mapViewImageForAnnotation = function (mapView, annotation) {
138
+ var cachedMarker = this.getTappedMarkerDetails(annotation);
139
+ if (cachedMarker) {
140
+ if (cachedMarker.reuseIdentifier) {
141
+ var reusedImage = mapView.dequeueReusableAnnotationImageWithIdentifier(cachedMarker.reuseIdentifier);
142
+ if (reusedImage) {
143
+ return reusedImage;
144
+ }
145
+ }
146
+ // TODO try adding .rotatesToMatchCamera = true;
147
+ // .. for instance in the mapViewDidDeselectAnnotationView / mapViewDidSelectAnnotationView / mapViewViewForAnnotation delegate
148
+ if (cachedMarker.icon) {
149
+ if (cachedMarker.icon.startsWith('res://')) {
150
+ var resourceName = cachedMarker.icon.substring('res://'.length);
151
+ var imageSource = ImageSource.fromResourceSync(resourceName);
152
+ if (imageSource === null) {
153
+ console.log("Unable to locate ".concat(resourceName));
154
+ }
155
+ else {
156
+ cachedMarker.reuseIdentifier = cachedMarker.icon;
157
+ return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(imageSource.ios, cachedMarker.reuseIdentifier);
158
+ }
159
+ }
160
+ else if (cachedMarker.icon.startsWith('http')) {
161
+ if (cachedMarker.iconDownloaded !== null) {
162
+ cachedMarker.reuseIdentifier = cachedMarker.icon;
163
+ return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(cachedMarker.iconDownloaded, cachedMarker.reuseIdentifier);
164
+ }
165
+ }
166
+ else {
167
+ if (Trace.isEnabled()) {
168
+ CLog(CLogTypes.info, 'Please use res://resourceName, http(s)://imageUrl or iconPath to use a local path');
169
+ }
170
+ }
171
+ }
172
+ else if (cachedMarker.iconPath) {
173
+ var appPath = knownFolders.currentApp().path;
174
+ var iconFullPath = appPath + '/' + cachedMarker.iconPath.replace('~/', '');
175
+ if (File.exists(iconFullPath)) {
176
+ var image = ImageSource.fromFileSync(iconFullPath).ios;
177
+ // perhaps add resize options for nice retina rendering (although you can now use the 'icon' param instead)
178
+ cachedMarker.reuseIdentifier = cachedMarker.iconPath;
179
+ return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(image, cachedMarker.reuseIdentifier);
180
+ }
181
+ }
182
+ }
183
+ return null;
184
+ };
185
+ /**
186
+ * fired when one of the callout's accessoryviews is tapped (not currently used)
187
+ */
188
+ MGLMapViewDelegateImpl.prototype.mapViewAnnotationCalloutAccessoryControlTapped = function (mapView, annotation, control) { };
189
+ /**
190
+ * fired when a marker is tapped
191
+ */
192
+ MGLMapViewDelegateImpl.prototype.mapViewDidSelectAnnotation = function (mapView, annotation) {
193
+ if (Trace.isEnabled()) {
194
+ CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidSelectAnntation()');
195
+ }
196
+ if (annotation.isKindOfClass(MGLUserLocation.class())) {
197
+ if (Trace.isEnabled()) {
198
+ CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidSelectAnnotation(): tapped the user location button');
199
+ }
200
+ if (typeof this.userLocationClickListener != 'undefined') {
201
+ this.userLocationClickListener(annotation);
202
+ return;
203
+ }
204
+ mapView.deselectAnnotationAnimated(annotation, false);
205
+ }
206
+ var cachedMarker = this.getTappedMarkerDetails(annotation);
207
+ if (cachedMarker && cachedMarker.onTap) {
208
+ cachedMarker.onTap(cachedMarker);
209
+ }
210
+ };
211
+ /**
212
+ * fired when a callout is tapped
213
+ */
214
+ MGLMapViewDelegateImpl.prototype.mapViewTapOnCalloutForAnnotation = function (mapView, annotation) {
215
+ var cachedMarker = this.getTappedMarkerDetails(annotation);
216
+ if (cachedMarker && cachedMarker.onCalloutTap) {
217
+ cachedMarker.onCalloutTap(cachedMarker);
218
+ }
219
+ };
220
+ MGLMapViewDelegateImpl.prototype.getTappedMarkerDetails = function (tapped) {
221
+ for (var m in _markers) {
222
+ var cached = _markers[m];
223
+ // don't compare lat/lng types as they're not the same (same for (sub)title, they may be null vs undefined)
224
+ if (
225
+ // eslint-disable-next-line eqeqeq
226
+ cached.lat == tapped.coordinate.latitude &&
227
+ // eslint-disable-next-line eqeqeq
228
+ cached.lng == tapped.coordinate.longitude &&
229
+ // eslint-disable-next-line eqeqeq
230
+ cached.title == tapped.title &&
231
+ // eslint-disable-next-line eqeqeq
232
+ cached.subtitle == tapped.subtitle) {
233
+ return cached;
234
+ }
235
+ }
236
+ };
237
+ /**
238
+ * override the standard location marker
239
+ */
240
+ MGLMapViewDelegateImpl.prototype.mapViewViewForAnnotation = function (mapView, annotation) {
241
+ if (Trace.isEnabled()) {
242
+ CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewViewForAnnotation() top');
243
+ }
244
+ if (annotation.isKindOfClass(MGLUserLocation.class())) {
245
+ this.userLocationAnnotationView = CustomUserLocationAnnotationView.alloc().init();
246
+ return this.userLocationAnnotationView;
247
+ }
248
+ return null;
249
+ };
250
+ MGLMapViewDelegateImpl.prototype.mapViewRegionIsChangingWithReason = function (mapView, reason) {
251
+ if (Trace.isEnabled()) {
252
+ CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionIsChanging()');
253
+ }
254
+ if (this.cameraChangedListener) {
255
+ this.cameraChangedListener(reason);
256
+ }
257
+ };
258
+ MGLMapViewDelegateImpl.prototype.mapViewRegionDidChangeWithReasonAnimated = function (mapView, reason, animated) {
259
+ if (Trace.isEnabled()) {
260
+ CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionDidChangeAnimated()');
261
+ }
262
+ if (this.cameraChangedListener) {
263
+ this.cameraChangedListener(reason, animated);
264
+ }
265
+ if (this.cameraIdledListener) {
266
+ this.cameraIdledListener();
267
+ }
268
+ };
269
+ MGLMapViewDelegateImpl.prototype.mapViewDidUpdateUserLocation = function (mapView, userLocation) {
270
+ if (Trace.isEnabled()) {
271
+ CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidUpdateUserLocation()');
272
+ }
273
+ if (this.userLocationChangedListener) {
274
+ this.userLocationChangedListener(_getLocation(userLocation));
275
+ }
276
+ };
277
+ MGLMapViewDelegateImpl.ObjCProtocols = [MGLMapViewDelegate];
278
+ return MGLMapViewDelegateImpl;
279
+ }(NSObject));
280
+ var MapTapHandlerImpl = /** @class */ (function (_super) {
281
+ __extends(MapTapHandlerImpl, _super);
282
+ function MapTapHandlerImpl() {
283
+ return _super !== null && _super.apply(this, arguments) || this;
284
+ }
285
+ MapTapHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, mapView) {
286
+ var handler = MapTapHandlerImpl.new();
287
+ handler._owner = owner;
288
+ handler._listener = listener;
289
+ handler._mapView = mapView;
290
+ return handler;
291
+ };
292
+ MapTapHandlerImpl.prototype.tap = function (recognizer) {
293
+ var tapPoint = recognizer.locationInView(this._mapView);
294
+ var tapCoordinate = this._mapView.convertPointToCoordinateFromView(tapPoint, this._mapView);
295
+ this._listener({
296
+ lat: tapCoordinate.latitude,
297
+ lng: tapCoordinate.longitude
298
+ });
299
+ };
300
+ MapTapHandlerImpl.ObjCExposedMethods = {
301
+ tap: { returns: interop.types.void, params: [interop.types.id] }
302
+ };
303
+ return MapTapHandlerImpl;
304
+ }(NSObject));
305
+ var MapLongPressHandlerImpl = /** @class */ (function (_super) {
306
+ __extends(MapLongPressHandlerImpl, _super);
307
+ function MapLongPressHandlerImpl() {
308
+ return _super !== null && _super.apply(this, arguments) || this;
309
+ }
310
+ MapLongPressHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, mapView) {
311
+ var handler = MapLongPressHandlerImpl.new();
312
+ handler._owner = owner;
313
+ handler._listener = listener;
314
+ handler._mapView = mapView;
315
+ return handler;
316
+ };
317
+ MapLongPressHandlerImpl.prototype.longPress = function (recognizer) {
318
+ var longPressPoint = recognizer.locationInView(this._mapView);
319
+ var longPressCoordinate = this._mapView.convertPointToCoordinateFromView(longPressPoint, this._mapView);
320
+ this._listener({
321
+ lat: longPressCoordinate.latitude,
322
+ lng: longPressCoordinate.longitude
323
+ });
324
+ };
325
+ MapLongPressHandlerImpl.ObjCExposedMethods = {
326
+ longPress: { returns: interop.types.void, params: [interop.types.id] }
327
+ };
328
+ return MapLongPressHandlerImpl;
329
+ }(NSObject));
330
+ var MapPanHandlerImpl = /** @class */ (function (_super) {
331
+ __extends(MapPanHandlerImpl, _super);
332
+ function MapPanHandlerImpl() {
333
+ return _super !== null && _super.apply(this, arguments) || this;
334
+ }
335
+ MapPanHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, panState, mapView) {
336
+ var handler = MapPanHandlerImpl.new();
337
+ handler._owner = owner;
338
+ handler._listener = new Map([[panState, listener]]);
339
+ handler._mapView = mapView;
340
+ return handler;
341
+ };
342
+ MapPanHandlerImpl.prototype.addListener = function (panState, listener) {
343
+ this._listener.set(panState, listener);
344
+ };
345
+ MapPanHandlerImpl.prototype.pan = function (recognizer) {
346
+ var panCoordinate = this.getCoordinates(recognizer);
347
+ if (Trace.isEnabled()) {
348
+ CLog(CLogTypes.info, 'MapPanHandlerImpl::pan(): top with state:', recognizer.state);
349
+ }
350
+ if (recognizer.state === UIGestureRecognizerState.Changed) {
351
+ this.notifyListener(recognizer.state, panCoordinate.latitude, panCoordinate.longitude);
352
+ }
353
+ };
354
+ MapPanHandlerImpl.prototype.panEnd = function (recognizer) {
355
+ var panCoordinate = this.getCoordinates(recognizer);
356
+ if (Trace.isEnabled()) {
357
+ CLog(CLogTypes.info, 'MapPanHandlerImpl::panEnd(): top with state:', recognizer.state);
358
+ }
359
+ if (recognizer.state === UIGestureRecognizerState.Ended) {
360
+ this.notifyListener(recognizer.state, panCoordinate.latitude, panCoordinate.longitude);
361
+ }
362
+ };
363
+ MapPanHandlerImpl.prototype.panBegin = function (recognizer) {
364
+ var panCoordinate = this.getCoordinates(recognizer);
365
+ if (Trace.isEnabled()) {
366
+ CLog(CLogTypes.info, 'MapPanHandlerImpl::panBegin(): top with state:', recognizer.state);
367
+ }
368
+ if (recognizer.state === UIGestureRecognizerState.Began) {
369
+ this.notifyListener(recognizer.state, panCoordinate.latitude, panCoordinate.longitude);
370
+ }
371
+ };
372
+ MapPanHandlerImpl.prototype.getCoordinates = function (recognizer) {
373
+ var panPoint = recognizer.locationInView(this._mapView);
374
+ return this._mapView.convertPointToCoordinateFromView(panPoint, this._mapView);
375
+ };
376
+ MapPanHandlerImpl.prototype.notifyListener = function (panState, latitude, longitude) {
377
+ if (this._listener.has(panState)) {
378
+ this._listener.get(panState)({ lat: latitude, lng: longitude });
379
+ }
380
+ };
381
+ MapPanHandlerImpl.ObjCExposedMethods = {
382
+ pan: { returns: interop.types.void, params: [interop.types.id] },
383
+ panEnd: { returns: interop.types.void, params: [interop.types.id] },
384
+ panBegin: { returns: interop.types.void, params: [interop.types.id] }
385
+ };
386
+ return MapPanHandlerImpl;
387
+ }(NSObject));
388
+ var MapSwipeHandlerImpl = /** @class */ (function (_super) {
389
+ __extends(MapSwipeHandlerImpl, _super);
390
+ function MapSwipeHandlerImpl() {
391
+ return _super !== null && _super.apply(this, arguments) || this;
392
+ }
393
+ MapSwipeHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, mapView) {
394
+ var handler = MapSwipeHandlerImpl.new();
395
+ handler._owner = owner;
396
+ handler._listener = listener;
397
+ handler._mapView = mapView;
398
+ return handler;
399
+ };
400
+ MapSwipeHandlerImpl.prototype.swipe = function (recognizer) {
401
+ var swipePoint = recognizer.locationInView(this._mapView);
402
+ var swipeCoordinate = this._mapView.convertPointToCoordinateFromView(swipePoint, this._mapView);
403
+ this._listener({
404
+ lat: swipeCoordinate.latitude,
405
+ lng: swipeCoordinate.longitude
406
+ });
407
+ };
408
+ MapSwipeHandlerImpl.ObjCExposedMethods = {
409
+ swipe: { returns: interop.types.void, params: [interop.types.id] }
410
+ };
411
+ return MapSwipeHandlerImpl;
412
+ }(NSObject));
413
+ export * from './common';
8
414
  let _markers = [];
9
415
  const _markerIconDownloadCache = [];
10
416
  const _setMapboxMapOptions = (mapView, settings) => {
@@ -219,6 +625,28 @@ export class MapboxView extends MapboxViewBase {
219
625
  ios: this.nativeMapView
220
626
  });
221
627
  }, this.nativeMapView);
628
+ this.mapbox.setOnMoveEndListener((data) => {
629
+ if (Trace.isEnabled()) {
630
+ CLog(CLogTypes.info, 'initMap(): onMoveEnd listener');
631
+ }
632
+ this.notify({
633
+ eventName: MapboxViewBase.moveEndEvent,
634
+ object: this,
635
+ map: this,
636
+ ios: this.nativeMapView
637
+ });
638
+ }, this.nativeMapView);
639
+ this.mapbox.setOnScrollListener((data) => {
640
+ if (Trace.isEnabled()) {
641
+ CLog(CLogTypes.info, 'initMap(): onScroll listener');
642
+ }
643
+ this.notify({
644
+ eventName: MapboxViewBase.scrollEvent,
645
+ object: this,
646
+ map: this,
647
+ ios: this.nativeMapView
648
+ });
649
+ }, this.nativeMapView);
222
650
  };
223
651
  setTimeout(drawMap, this.settings.delay ? this.settings.delay : 0);
224
652
  }
@@ -233,9 +661,6 @@ export class MapboxView extends MapboxViewBase {
233
661
  NSUserDefaults.standardUserDefaults.setBoolForKey(false, 'MGLMapboxMetricsEnabled');
234
662
  }
235
663
  }
236
- "use strict";
237
- Object.defineProperty(exports, "__esModule", { value: true });
238
- exports.CustomUserLocationAnnotationView = void 0;
239
664
  var CustomUserLocationAnnotationView = /** @class */ (function (_super) {
240
665
  __extends(CustomUserLocationAnnotationView, _super);
241
666
  function CustomUserLocationAnnotationView() {
@@ -444,7 +869,6 @@ var CustomUserLocationAnnotationView = /** @class */ (function (_super) {
444
869
  };
445
870
  return CustomUserLocationAnnotationView;
446
871
  }(MGLUserLocationAnnotationView));
447
- exports.CustomUserLocationAnnotationView = CustomUserLocationAnnotationView;
448
872
  export class Mapbox extends MapboxCommon {
449
873
  constructor() {
450
874
  super(...arguments);
@@ -825,403 +1249,41 @@ export class Mapbox extends MapboxCommon {
825
1249
  const level = options.level;
826
1250
  if (level >= 0 && level <= 20) {
827
1251
  theMap.setZoomLevelAnimated(level, animated);
828
- resolve();
829
- }
830
- else {
831
- reject('invalid ZoomLevel, use any double value from 0 to 20 (like 8.3)');
832
- }
833
- }
834
- catch (ex) {
835
- if (Trace.isEnabled()) {
836
- CLog(CLogTypes.info, 'Error in mapbox.setZoomLevel: ' + ex);
837
- }
838
- reject(ex);
839
- }
840
- });
841
- }
842
- getZoomLevel(nativeMap) {
843
- return new Promise((resolve, reject) => {
844
- try {
845
- const theMap = nativeMap || this._mapboxViewInstance;
846
- resolve(theMap.zoomLevel);
847
- }
848
- catch (ex) {
849
- if (Trace.isEnabled()) {
850
- CLog(CLogTypes.info, 'Error in mapbox.getZoomLevel: ' + ex);
851
- }
852
- reject(ex);
853
- }
854
- });
855
- }
856
- setTilt(options, nativeMap) {
857
- return new Promise((resolve, reject) => {
858
- try {
859
- const theMap = nativeMap || this._mapboxViewInstance;
860
- const cam = theMap.camera;
861
- cam.pitch = options.tilt;
862
- const durationMs = options.duration ? options.duration : 5000;
863
- theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
864
- setTimeout(() => {
865
- resolve();
866
- }, durationMs);
867
- }
868
- catch (ex) {
869
- if (Trace.isEnabled()) {
870
- CLog(CLogTypes.info, 'Error in mapbox.setTilt: ' + ex);
871
- }
872
- reject(ex);
873
- }
874
- });
875
- }
876
- getTilt(nativeMap) {
877
- return new Promise((resolve, reject) => {
878
- try {
879
- const theMap = nativeMap || this._mapboxViewInstance;
880
- resolve(theMap.camera.pitch);
881
- }
882
- catch (ex) {
883
- if (Trace.isEnabled()) {
884
- CLog(CLogTypes.info, 'Error in mapbox.getTilt: ' + ex);
885
- }
886
- reject(ex);
887
- }
888
- });
889
- }
890
- getUserLocation(nativeMap) {
891
- return new Promise((resolve, reject) => {
892
- try {
893
- const theMap = nativeMap || this._mapboxViewInstance;
894
- const loc = theMap.userLocation;
895
- if (loc === null) {
896
- reject('Location not available');
897
- }
898
- else {
899
- resolve(_getLocation(loc));
900
- }
901
- }
902
- catch (ex) {
903
- if (Trace.isEnabled()) {
904
- CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
905
- }
906
- reject(ex);
907
- }
908
- });
909
- }
910
- _stringToCameraMode(mode) {
911
- switch (mode) {
912
- case 'NONE':
913
- return 0;
914
- case 'NONE_COMPASS':
915
- if (Trace.isEnabled()) {
916
- CLog(CLogTypes.info, '_stringToCameraMode(): NONE_COMPASS unsupported on iOS');
917
- }
918
- return 0;
919
- case 'NONE_GPS':
920
- if (Trace.isEnabled()) {
921
- CLog(CLogTypes.info, '_stringToCameraMode(): NONE_GPS unsupported on iOS');
922
- }
923
- return 0;
924
- case 'TRACKING':
925
- return 1;
926
- case 'TRACK_COMPASS':
927
- return 2;
928
- case 'TRACKING_GPS':
929
- return 1;
930
- case 'TRACK_GPS_NORTH':
931
- return 3;
932
- }
933
- }
934
- _stringToRenderMode(mode) {
935
- let renderMode;
936
- switch (mode) {
937
- case 'NORMAL':
938
- return 'NORMAL';
939
- case 'COMPASS':
940
- return 'COMPASS';
941
- case 'GPS':
942
- return 'GPS';
943
- }
944
- }
945
- showUserLocationMarker(options, nativeMap) {
946
- return new Promise((resolve, reject) => {
947
- try {
948
- const theMap = nativeMap || this._mapboxViewInstance;
949
- theMap.showsUserLocation = true;
950
- theMap.userTrackingMode = this._stringToCameraMode(options.cameraMode);
951
- theMap.showsUserHeadingIndicator = true;
952
- this.userLocationRenderMode = this._stringToRenderMode(options.renderMode);
953
- const delegate = theMap.delegate;
954
- delegate.changeUserLocationRenderMode(this.userLocationRenderMode);
955
- if (typeof options.clickListener != 'undefined') {
956
- delegate.setUserLocationClickListener(options.clickListener);
957
- }
958
- resolve();
959
- }
960
- catch (ex) {
961
- if (Trace.isEnabled()) {
962
- CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
963
- }
964
- reject(ex);
965
- }
966
- });
967
- }
968
- hideUserLocationMarker(nativeMap) {
969
- return new Promise((resolve, reject) => {
970
- try {
971
- resolve();
972
- }
973
- catch (ex) {
974
- if (Trace.isEnabled()) {
975
- CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
976
- }
977
- reject(ex);
978
- }
979
- });
980
- }
981
- changeUserLocationMarkerMode(renderModeString, cameraModeString, nativeMap) {
982
- return new Promise((resolve, reject) => {
983
- try {
984
- const theMap = nativeMap || this._mapboxViewInstance;
985
- if (Trace.isEnabled()) {
986
- CLog(CLogTypes.info, "Mapbox::changeUserLocationMarkerMode(): changing renderMode to '" + renderModeString + "' cameraMode '" + cameraModeString + "'");
987
- }
988
- theMap.userTrackingMode = this._stringToCameraMode(cameraModeString);
989
- const delegate = theMap.delegate;
990
- const renderMode = this._stringToRenderMode(renderModeString);
991
- delegate.changeUserLocationRenderMode(renderMode);
992
- }
993
- catch (ex) {
994
- if (Trace.isEnabled()) {
995
- CLog(CLogTypes.info, 'Error in mapbox.showUserLocationMarker: ' + ex);
996
- }
997
- reject(ex);
998
- }
999
- });
1000
- }
1001
- forceUserLocationUpdate(location, nativeMap) { }
1002
- queryRenderedFeatures(options, nativeMap) {
1003
- return new Promise((resolve, reject) => {
1004
- try {
1005
- const theMap = nativeMap || this._mapboxViewInstance;
1006
- if (options.point === undefined) {
1007
- reject("Please set the 'point' parameter");
1008
- return;
1009
- }
1010
- if (!options) {
1011
- options = {};
1012
- }
1013
- const { x, y } = theMap.convertCoordinateToPointToView({ latitude: options.point.lat, longitude: options.point.lng }, theMap);
1014
- const queryLayerIds = options.layers ? NSSet.setWithArray(iOSNativeHelper.collections.jsArrayToNSArray(options.layers)) : null;
1015
- const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
1016
- const features = theMap.visibleFeaturesAtPointInStyleLayersWithIdentifiersPredicate({ x, y }, queryLayerIds, queryFilter);
1017
- const result = [];
1018
- for (let i = 0; i < features.count; i++) {
1019
- const feature = features.objectAtIndex(i);
1020
- const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
1021
- result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding)));
1022
- }
1023
- resolve(result);
1024
- }
1025
- catch (ex) {
1026
- if (Trace.isEnabled()) {
1027
- CLog(CLogTypes.info, 'Error in mapbox.queryRenderedFeatures: ' + ex);
1028
- }
1029
- reject(ex);
1030
- }
1031
- });
1032
- }
1033
- querySourceFeatures(sourceId, options, nativeMap) {
1034
- return new Promise((resolve, reject) => {
1035
- try {
1036
- const theMap = nativeMap || this._mapboxViewInstance;
1037
- if (!options) {
1038
- options = {};
1039
- }
1040
- const source = theMap.style.sourceWithIdentifier(sourceId);
1041
- if (!source) {
1042
- throw new Error(`Source with id "${sourceId}" not found.`);
1043
- }
1044
- let features;
1045
- const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
1046
- if (source instanceof MGLShapeSource) {
1047
- features = source.featuresMatchingPredicate(queryFilter);
1048
- }
1049
- else if (source instanceof MGLVectorTileSource) {
1050
- if (!options.sourceLayer) {
1051
- throw new Error('The option "sourceLayer" is required for vector sources.');
1052
- }
1053
- const sourceLayerIds = options.sourceLayer ? NSSet.setWithArray(iOSNativeHelper.collections.jsArrayToNSArray([options.sourceLayer])) : null;
1054
- features = source.featuresInSourceLayersWithIdentifiersPredicate(sourceLayerIds, queryFilter);
1252
+ resolve();
1055
1253
  }
1056
1254
  else {
1057
- throw new Error('Only sources from type "vector" or "geojson" are supported.');
1058
- }
1059
- const result = [];
1060
- for (let i = 0; i < features.count; i++) {
1061
- const feature = features.objectAtIndex(i);
1062
- const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
1063
- result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding)));
1255
+ reject('invalid ZoomLevel, use any double value from 0 to 20 (like 8.3)');
1064
1256
  }
1065
- resolve(result);
1066
1257
  }
1067
1258
  catch (ex) {
1068
1259
  if (Trace.isEnabled()) {
1069
- CLog(CLogTypes.info, 'Error in mapbox.querySourceFeatures: ' + ex);
1260
+ CLog(CLogTypes.info, 'Error in mapbox.setZoomLevel: ' + ex);
1070
1261
  }
1071
1262
  reject(ex);
1072
1263
  }
1073
1264
  });
1074
1265
  }
1075
- addPolygon(options, nativeMap) {
1266
+ getZoomLevel(nativeMap) {
1076
1267
  return new Promise((resolve, reject) => {
1077
- const theMap = nativeMap || this._mapboxViewInstance;
1078
- const points = options.points;
1079
- if (points === undefined) {
1080
- reject("Please set the 'points' parameter");
1081
- return;
1082
- }
1083
- const coordinateArray = [];
1084
- points.forEach((point) => coordinateArray.push([point.lng, point.lat]));
1085
- const polygonID = `polygon_${options.id || new Date().getTime()}`;
1086
- if (theMap.style.sourceWithIdentifier(polygonID)) {
1087
- reject("Remove the polygon with this id first with 'removePolygons': " + polygonID);
1088
- return;
1268
+ try {
1269
+ const theMap = nativeMap || this._mapboxViewInstance;
1270
+ resolve(theMap.zoomLevel);
1089
1271
  }
1090
- const geoJSON = `{
1091
- "type": "FeatureCollection",
1092
- "features": [
1093
- {
1094
- "id": ${JSON.stringify(polygonID)},
1095
- "type": "Feature",
1096
- "properties": {
1097
- },
1098
- "geometry": {
1099
- "type": "Polygon",
1100
- "coordinates": [${JSON.stringify(coordinateArray)}]
1101
- }
1272
+ catch (ex) {
1273
+ if (Trace.isEnabled()) {
1274
+ CLog(CLogTypes.info, 'Error in mapbox.getZoomLevel: ' + ex);
1102
1275
  }
1103
- ]
1104
- }`;
1105
- const geoDataStr = NSString.stringWithString(geoJSON);
1106
- const geoData = geoDataStr.dataUsingEncoding(NSUTF8StringEncoding);
1107
- const geoDataBase64Enc = geoData.base64EncodedStringWithOptions(0);
1108
- const geo = NSData.alloc().initWithBase64EncodedStringOptions(geoDataBase64Enc, null);
1109
- const shape = MGLShape.shapeWithDataEncodingError(geo, NSUTF8StringEncoding);
1110
- const source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(polygonID, shape, null);
1111
- theMap.style.addSource(source);
1112
- if (options.strokeColor || options.strokeWidth || options.strokeOpacity) {
1113
- const strokeLayer = MGLLineStyleLayer.alloc().initWithIdentifierSource(polygonID + '_stroke', source);
1114
- strokeLayer.lineColor = NSExpression.expressionForConstantValue(!options.strokeColor ? UIColor.blackColor : options.strokeColor instanceof Color ? options.strokeColor.ios : new Color(options.strokeColor).ios);
1115
- strokeLayer.lineWidth = NSExpression.expressionForConstantValue(options.strokeWidth || 5);
1116
- strokeLayer.lineOpacity = NSExpression.expressionForConstantValue(options.strokeOpacity === undefined ? 1 : options.strokeOpacity);
1117
- theMap.style.addLayer(strokeLayer);
1118
- }
1119
- const layer = MGLFillStyleLayer.alloc().initWithIdentifierSource(polygonID, source);
1120
- layer.fillColor = NSExpression.expressionForConstantValue(!options.fillColor ? UIColor.blackColor : options.fillColor instanceof Color ? options.fillColor.ios : new Color(options.fillColor).ios);
1121
- layer.fillOpacity = NSExpression.expressionForConstantValue(options.fillOpacity === undefined ? 1 : options.fillOpacity);
1122
- theMap.style.addLayer(layer);
1123
- resolve();
1124
- });
1125
- }
1126
- addPolyline(options, nativeMap) {
1127
- return new Promise((resolve, reject) => {
1128
- const theMap = nativeMap || this._mapboxViewInstance;
1129
- const points = options.points;
1130
- if (points === undefined) {
1131
- reject("Please set the 'points' parameter");
1132
- return;
1133
- }
1134
- const coordinateArray = [];
1135
- points.forEach((point) => coordinateArray.push([point.lng, point.lat]));
1136
- const polylineID = 'polyline_' + (options.id || new Date().getTime());
1137
- if (theMap.style.sourceWithIdentifier(polylineID)) {
1138
- reject("Remove the polyline with this id first with 'removePolylines': " + polylineID);
1139
- return;
1276
+ reject(ex);
1140
1277
  }
1141
- const geoJSON = `{"type": "FeatureCollection", "features": [{"type": "Feature","properties": {},"geometry": {"type": "LineString", "coordinates": ${JSON.stringify(coordinateArray)}}}]}`;
1142
- const geoDataStr = NSString.stringWithString(geoJSON);
1143
- const geoData = geoDataStr.dataUsingEncoding(NSUTF8StringEncoding);
1144
- const geoDataBase64Enc = geoData.base64EncodedStringWithOptions(0);
1145
- const geo = NSData.alloc().initWithBase64EncodedStringOptions(geoDataBase64Enc, null);
1146
- const shape = MGLShape.shapeWithDataEncodingError(geo, NSUTF8StringEncoding);
1147
- const source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(polylineID, shape, null);
1148
- theMap.style.addSource(source);
1149
- const layer = MGLLineStyleLayer.alloc().initWithIdentifierSource(polylineID, source);
1150
- layer.lineColor = NSExpression.expressionForConstantValue(!options.color ? UIColor.blackColor : options.color instanceof Color ? options.color.ios : new Color(options.color).ios);
1151
- layer.lineWidth = NSExpression.expressionForConstantValue(options.width || 5);
1152
- layer.lineOpacity = NSExpression.expressionForConstantValue(options.opacity === undefined ? 1 : options.opacity);
1153
- theMap.style.addLayer(layer);
1154
- resolve();
1155
1278
  });
1156
1279
  }
1157
- removePolyById(theMap, id) {
1158
- let layer = theMap.style.layerWithIdentifier(id);
1159
- if (layer !== null) {
1160
- theMap.style.removeLayer(layer);
1161
- }
1162
- layer = theMap.style.layerWithIdentifier(id + '_stroke');
1163
- if (layer !== null) {
1164
- theMap.style.removeLayer(layer);
1165
- }
1166
- const source = theMap.style.sourceWithIdentifier(id);
1167
- if (source !== null) {
1168
- theMap.style.removeSource(source);
1169
- }
1170
- }
1171
- removePolys(polyType, ids, nativeMap) {
1172
- return new Promise((resolve) => {
1173
- const theMap = nativeMap || this._mapboxViewInstance;
1174
- ids.forEach((id) => this.removePolyById(theMap, polyType + id));
1175
- resolve();
1176
- });
1177
- }
1178
- removePolygons(ids, nativeMap) {
1179
- return this.removePolys('polygon_', ids, nativeMap);
1180
- }
1181
- removePolylines(ids, nativeMap) {
1182
- return this.removePolys('polyline_', ids, nativeMap);
1183
- }
1184
- animateCamera(options, nativeMap) {
1280
+ setTilt(options, nativeMap) {
1185
1281
  return new Promise((resolve, reject) => {
1186
1282
  try {
1187
1283
  const theMap = nativeMap || this._mapboxViewInstance;
1188
- let cam;
1189
- if (options.bounds) {
1190
- const padding = options.padding || 0;
1191
- const insets = {
1192
- top: padding,
1193
- left: padding,
1194
- bottom: padding,
1195
- right: padding
1196
- };
1197
- const bounds = {
1198
- sw: CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west),
1199
- ne: CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east)
1200
- };
1201
- cam = theMap.cameraThatFitsCoordinateBoundsEdgePadding(bounds, insets);
1202
- }
1203
- else {
1204
- const target = options.target;
1205
- if (target === undefined) {
1206
- reject("Please set the 'target' parameter");
1207
- return;
1208
- }
1209
- cam = theMap.camera;
1210
- cam.centerCoordinate = CLLocationCoordinate2DMake(target.lat, target.lng);
1211
- }
1212
- if (options.altitude) {
1213
- cam.altitude = options.altitude;
1214
- }
1215
- if (options.bearing) {
1216
- cam.heading = options.bearing;
1217
- }
1218
- if (options.tilt) {
1219
- cam.pitch = options.tilt;
1220
- }
1221
- if (options.zoomLevel && options.target) {
1222
- cam.altitude = MGLAltitudeForZoomLevel(options.zoomLevel, cam.pitch, options.target.lat, theMap.frame.size);
1223
- }
1224
- const durationMs = options.duration ? options.duration : 10000;
1284
+ const cam = theMap.camera;
1285
+ cam.pitch = options.tilt;
1286
+ const durationMs = options.duration ? options.duration : 5000;
1225
1287
  theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
1226
1288
  setTimeout(() => {
1227
1289
  resolve();
@@ -1229,336 +1291,375 @@ export class Mapbox extends MapboxCommon {
1229
1291
  }
1230
1292
  catch (ex) {
1231
1293
  if (Trace.isEnabled()) {
1232
- CLog(CLogTypes.info, 'Error in mapbox.animateCamera: ' + ex);
1294
+ CLog(CLogTypes.info, 'Error in mapbox.setTilt: ' + ex);
1233
1295
  }
1234
1296
  reject(ex);
1235
1297
  }
1236
1298
  });
1237
1299
  }
1238
- setOnMapClickListener(listener, nativeMap) {
1300
+ getTilt(nativeMap) {
1239
1301
  return new Promise((resolve, reject) => {
1240
1302
  try {
1241
1303
  const theMap = nativeMap || this._mapboxViewInstance;
1242
- if (!theMap) {
1243
- reject('No map has been loaded');
1244
- return;
1245
- }
1246
- theMap['mapTapHandler'] = MapTapHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
1247
- const tapGestureRecognizer = UITapGestureRecognizer.alloc().initWithTargetAction(theMap['mapTapHandler'], 'tap');
1248
- for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1249
- const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1250
- if (recognizer instanceof UITapGestureRecognizer) {
1251
- tapGestureRecognizer.requireGestureRecognizerToFail(recognizer);
1252
- }
1253
- }
1254
- theMap.addGestureRecognizer(tapGestureRecognizer);
1255
- resolve();
1304
+ resolve(theMap.camera.pitch);
1256
1305
  }
1257
1306
  catch (ex) {
1258
1307
  if (Trace.isEnabled()) {
1259
- CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
1308
+ CLog(CLogTypes.info, 'Error in mapbox.getTilt: ' + ex);
1260
1309
  }
1261
1310
  reject(ex);
1262
1311
  }
1263
1312
  });
1264
1313
  }
1265
- setOnMapLongClickListener(listener, nativeMap) {
1314
+ getUserLocation(nativeMap) {
1266
1315
  return new Promise((resolve, reject) => {
1267
1316
  try {
1268
1317
  const theMap = nativeMap || this._mapboxViewInstance;
1269
- if (!theMap) {
1270
- reject('No map has been loaded');
1271
- return;
1318
+ const loc = theMap.userLocation;
1319
+ if (loc === null) {
1320
+ reject('Location not available');
1272
1321
  }
1273
- theMap['mapLongPressHandler'] = MapLongPressHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
1274
- const longPressGestureRecognizer = UILongPressGestureRecognizer.alloc().initWithTargetAction(theMap['mapLongPressHandler'], 'longPress');
1275
- for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1276
- const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1277
- if (recognizer instanceof UILongPressGestureRecognizer) {
1278
- longPressGestureRecognizer.requireGestureRecognizerToFail(recognizer);
1279
- }
1322
+ else {
1323
+ resolve(_getLocation(loc));
1280
1324
  }
1281
- theMap.addGestureRecognizer(longPressGestureRecognizer);
1282
- resolve();
1283
1325
  }
1284
1326
  catch (ex) {
1285
1327
  if (Trace.isEnabled()) {
1286
- CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
1328
+ CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
1287
1329
  }
1288
1330
  reject(ex);
1289
1331
  }
1290
1332
  });
1291
1333
  }
1292
- setOnScrollListener(listener, nativeMap) {
1334
+ _stringToCameraMode(mode) {
1335
+ switch (mode) {
1336
+ case 'NONE':
1337
+ return 0;
1338
+ case 'NONE_COMPASS':
1339
+ if (Trace.isEnabled()) {
1340
+ CLog(CLogTypes.info, '_stringToCameraMode(): NONE_COMPASS unsupported on iOS');
1341
+ }
1342
+ return 0;
1343
+ case 'NONE_GPS':
1344
+ if (Trace.isEnabled()) {
1345
+ CLog(CLogTypes.info, '_stringToCameraMode(): NONE_GPS unsupported on iOS');
1346
+ }
1347
+ return 0;
1348
+ case 'TRACKING':
1349
+ return 1;
1350
+ case 'TRACKING_COMPASS':
1351
+ return 2;
1352
+ case 'TRACKING_GPS':
1353
+ return 1;
1354
+ case 'TRACKING_GPS_NORTH':
1355
+ return 3;
1356
+ }
1357
+ }
1358
+ _stringToRenderMode(mode) {
1359
+ let renderMode;
1360
+ switch (mode) {
1361
+ case 'NORMAL':
1362
+ return 'NORMAL';
1363
+ case 'COMPASS':
1364
+ return 'COMPASS';
1365
+ case 'GPS':
1366
+ return 'GPS';
1367
+ }
1368
+ }
1369
+ showUserLocationMarker(options, nativeMap) {
1293
1370
  return new Promise((resolve, reject) => {
1294
1371
  try {
1295
1372
  const theMap = nativeMap || this._mapboxViewInstance;
1296
- if (!theMap) {
1297
- reject('No map has been loaded');
1298
- return;
1299
- }
1300
- theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
1301
- for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1302
- const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1303
- if (recognizer instanceof UIPanGestureRecognizer) {
1304
- recognizer.addTargetAction(theMap['mapPanHandler'], 'pan');
1305
- break;
1306
- }
1373
+ theMap.showsUserLocation = true;
1374
+ theMap.userTrackingMode = this._stringToCameraMode(options.cameraMode);
1375
+ theMap.showsUserHeadingIndicator = true;
1376
+ this.userLocationRenderMode = this._stringToRenderMode(options.renderMode);
1377
+ const delegate = theMap.delegate;
1378
+ delegate.changeUserLocationRenderMode(this.userLocationRenderMode);
1379
+ if (typeof options.clickListener != 'undefined') {
1380
+ delegate.setUserLocationClickListener(options.clickListener);
1307
1381
  }
1308
1382
  resolve();
1309
1383
  }
1310
1384
  catch (ex) {
1311
1385
  if (Trace.isEnabled()) {
1312
- CLog(CLogTypes.info, 'Error in mapbox.setOnScrollListener: ' + ex);
1386
+ CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
1313
1387
  }
1314
1388
  reject(ex);
1315
1389
  }
1316
1390
  });
1317
1391
  }
1318
- setOnMoveBeginListener(listener, nativeMap) {
1392
+ hideUserLocationMarker(nativeMap) {
1319
1393
  return new Promise((resolve, reject) => {
1320
1394
  try {
1321
- const theMap = nativeMap || this._mapboxViewInstance;
1322
- if (!theMap) {
1323
- reject('No map has been loaded');
1324
- return;
1325
- }
1326
- theMap['mapOnMoveBeginHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
1327
- theMap['mapOnMoveBeginHandler'].setOnMoveBegin();
1328
- for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1329
- const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1330
- if (recognizer instanceof UIPanGestureRecognizer) {
1331
- recognizer.addTargetAction(theMap['mapOnMoveBeginHandler'], 'pan');
1332
- break;
1333
- }
1334
- }
1335
1395
  resolve();
1336
1396
  }
1337
1397
  catch (ex) {
1338
1398
  if (Trace.isEnabled()) {
1339
- CLog(CLogTypes.info, 'Error in mapbox.setOnScrollListener: ' + ex);
1399
+ CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
1340
1400
  }
1341
1401
  reject(ex);
1342
1402
  }
1343
1403
  });
1344
1404
  }
1345
- setOnFlingListener(listener, nativeMap) {
1346
- return Promise.reject("'setOnFlingListener' is not supported on iOS");
1347
- }
1348
- async setOnCameraMoveListener(listener, nativeMap) {
1349
- const theMap = nativeMap || this._mapboxViewInstance;
1350
- if (theMap) {
1351
- theMap.delegate.setCameraChangedListener(listener);
1352
- }
1353
- else {
1354
- return Promise.reject('No map has been loaded');
1355
- }
1356
- }
1357
- setOnCameraMoveCancelListener(listener, nativeMap) {
1358
- return Promise.reject("'setOnCameraMoveCancelListener' not currently supported on iOS");
1359
- }
1360
- async setOnCameraIdleListener(listener, nativeMap) {
1361
- const theMap = nativeMap || this._mapboxViewInstance;
1362
- if (theMap) {
1363
- theMap.delegate.setCameraIdledListener(listener);
1364
- }
1365
- else {
1366
- return Promise.reject('No map has been loaded');
1367
- }
1368
- }
1369
- getViewport(nativeMap) {
1405
+ changeUserLocationMarkerMode(renderModeString, cameraModeString, nativeMap) {
1370
1406
  return new Promise((resolve, reject) => {
1371
1407
  try {
1372
1408
  const theMap = nativeMap || this._mapboxViewInstance;
1373
- if (!theMap) {
1374
- reject('No map has been loaded');
1375
- return;
1409
+ if (Trace.isEnabled()) {
1410
+ CLog(CLogTypes.info, "Mapbox::changeUserLocationMarkerMode(): changing renderMode to '" + renderModeString + "' cameraMode '" + cameraModeString + "'");
1376
1411
  }
1377
- const visibleBounds = theMap.visibleCoordinateBounds;
1378
- const bounds = {
1379
- north: visibleBounds.ne.latitude,
1380
- east: visibleBounds.ne.longitude,
1381
- south: visibleBounds.sw.latitude,
1382
- west: visibleBounds.sw.longitude
1383
- };
1384
- resolve({
1385
- bounds,
1386
- zoomLevel: theMap.zoomLevel
1387
- });
1412
+ theMap.userTrackingMode = this._stringToCameraMode(cameraModeString);
1413
+ const delegate = theMap.delegate;
1414
+ const renderMode = this._stringToRenderMode(renderModeString);
1415
+ delegate.changeUserLocationRenderMode(renderMode);
1388
1416
  }
1389
1417
  catch (ex) {
1390
1418
  if (Trace.isEnabled()) {
1391
- CLog(CLogTypes.info, 'Error in mapbox.getViewport: ' + ex);
1419
+ CLog(CLogTypes.info, 'Error in mapbox.showUserLocationMarker: ' + ex);
1392
1420
  }
1393
1421
  reject(ex);
1394
1422
  }
1395
1423
  });
1396
1424
  }
1397
- setViewport(options, nativeMap) {
1425
+ forceUserLocationUpdate(location, nativeMap) { }
1426
+ queryRenderedFeatures(options, nativeMap) {
1398
1427
  return new Promise((resolve, reject) => {
1399
1428
  try {
1400
1429
  const theMap = nativeMap || this._mapboxViewInstance;
1401
- if (!theMap) {
1402
- reject('No map has been loaded');
1430
+ if (options.point === undefined) {
1431
+ reject("Please set the 'point' parameter");
1403
1432
  return;
1404
1433
  }
1405
- const bounds = {
1406
- sw: CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west),
1407
- ne: CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east)
1408
- };
1409
- const animated = options.animated === undefined || options.animated;
1410
- const padding = options.padding !== undefined ? { top: options.padding, left: options.padding, bottom: options.padding, right: options.padding } : { top: 25, left: 25, bottom: 25, right: 25 };
1411
- theMap.setVisibleCoordinateBoundsEdgePaddingAnimated(bounds, padding, animated);
1412
- resolve();
1434
+ if (!options) {
1435
+ options = {};
1436
+ }
1437
+ const { x, y } = theMap.convertCoordinateToPointToView({ latitude: options.point.lat, longitude: options.point.lng }, theMap);
1438
+ const queryLayerIds = options.layers ? NSSet.setWithArray(Utils.ios.collections.jsArrayToNSArray(options.layers)) : null;
1439
+ const queryFilter = options.filter ? ExpressionParser.parseJson(options.filter) : null;
1440
+ const features = theMap.visibleFeaturesAtPointInStyleLayersWithIdentifiersPredicate({ x, y }, queryLayerIds, queryFilter);
1441
+ const result = [];
1442
+ for (let i = 0; i < features.count; i++) {
1443
+ const feature = features.objectAtIndex(i);
1444
+ const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
1445
+ result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding)));
1446
+ }
1447
+ resolve(result);
1413
1448
  }
1414
1449
  catch (ex) {
1415
1450
  if (Trace.isEnabled()) {
1416
- CLog(CLogTypes.info, 'Error in mapbox.setViewport: ' + ex);
1451
+ CLog(CLogTypes.info, 'Error in mapbox.queryRenderedFeatures: ' + ex);
1417
1452
  }
1418
1453
  reject(ex);
1419
1454
  }
1420
1455
  });
1421
1456
  }
1422
- downloadOfflineRegion(options) {
1457
+ querySourceFeatures(sourceId, options, nativeMap) {
1423
1458
  return new Promise((resolve, reject) => {
1424
1459
  try {
1425
- const styleURL = _getMapStyle(options.style);
1426
- const swCoordinate = CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west);
1427
- const neCoordinate = CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east);
1428
- const bounds = {
1429
- sw: swCoordinate,
1430
- ne: neCoordinate
1431
- };
1432
- const region = MGLTilePyramidOfflineRegion.alloc().initWithStyleURLBoundsFromZoomLevelToZoomLevel(styleURL, bounds, options.minZoom, options.maxZoom);
1433
- if (options.accessToken) {
1434
- MGLAccountManager.accessToken = options.accessToken;
1460
+ const theMap = nativeMap || this._mapboxViewInstance;
1461
+ if (!options) {
1462
+ options = {};
1435
1463
  }
1436
- if (options.onProgress) {
1437
- _addObserver(MGLOfflinePackProgressChangedNotification, (notification) => {
1438
- const offlinePack = notification.object;
1439
- const offlinePackProgress = offlinePack.progress;
1440
- const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1441
- const complete = offlinePackProgress.countOfResourcesCompleted === offlinePackProgress.countOfResourcesExpected;
1442
- options.onProgress({
1443
- name: userInfo.objectForKey('name'),
1444
- completed: offlinePackProgress.countOfResourcesCompleted,
1445
- expected: offlinePackProgress.countOfResourcesExpected,
1446
- percentage: Math.round((offlinePackProgress.countOfResourcesCompleted / offlinePackProgress.countOfResourcesExpected) * 10000) / 100,
1447
- complete
1448
- });
1449
- if (complete) {
1450
- resolve();
1451
- }
1452
- });
1464
+ const source = theMap.style.sourceWithIdentifier(sourceId);
1465
+ if (!source) {
1466
+ throw new Error(`Source with id "${sourceId}" not found.`);
1453
1467
  }
1454
- _addObserver(MGLOfflinePackErrorNotification, (notification) => {
1455
- const offlinePack = notification.object;
1456
- const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1457
- const error = notification.userInfo[MGLOfflinePackUserInfoKeyError];
1458
- reject({
1459
- name: userInfo.objectForKey('name'),
1460
- error: 'Download error. ' + error
1461
- });
1462
- });
1463
- _addObserver(MGLOfflinePackMaximumMapboxTilesReachedNotification, (notification) => {
1464
- const offlinePack = notification.object;
1465
- const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1466
- const maximumCount = notification.userInfo[MGLOfflinePackUserInfoKeyMaximumCount];
1467
- console.log(`Offline region '${userInfo.objectForKey('name')}' reached the tile limit of ${maximumCount}`);
1468
- });
1469
- const userInfo = { name: options.name };
1470
- const context = NSKeyedArchiver.archivedDataWithRootObject(userInfo);
1471
- MGLOfflineStorage.sharedOfflineStorage.addPackForRegionWithContextCompletionHandler(region, context, (pack, error) => {
1472
- if (error) {
1473
- reject(error.localizedFailureReason);
1474
- }
1475
- else {
1476
- pack.resume();
1468
+ let features;
1469
+ const queryFilter = options.filter ? ExpressionParser.parseJson(options.filter) : null;
1470
+ if (source instanceof MGLShapeSource) {
1471
+ features = source.featuresMatchingPredicate(queryFilter);
1472
+ }
1473
+ else if (source instanceof MGLVectorTileSource) {
1474
+ if (!options.sourceLayer) {
1475
+ throw new Error('The option "sourceLayer" is required for vector sources.');
1477
1476
  }
1478
- });
1477
+ const sourceLayerIds = options.sourceLayer ? NSSet.setWithArray(Utils.ios.collections.jsArrayToNSArray([options.sourceLayer])) : null;
1478
+ features = source.featuresInSourceLayersWithIdentifiersPredicate(sourceLayerIds, queryFilter);
1479
+ }
1480
+ else {
1481
+ throw new Error('Only sources from type "vector" or "geojson" are supported.');
1482
+ }
1483
+ const result = [];
1484
+ for (let i = 0; i < features.count; i++) {
1485
+ const feature = features.objectAtIndex(i);
1486
+ const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
1487
+ result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding)));
1488
+ }
1489
+ resolve(result);
1479
1490
  }
1480
1491
  catch (ex) {
1481
1492
  if (Trace.isEnabled()) {
1482
- CLog(CLogTypes.info, 'Error in mapbox.downloadOfflineRegion: ' + ex);
1493
+ CLog(CLogTypes.info, 'Error in mapbox.querySourceFeatures: ' + ex);
1483
1494
  }
1484
1495
  reject(ex);
1485
1496
  }
1486
1497
  });
1487
1498
  }
1488
- listOfflineRegions(options) {
1499
+ addPolygon(options, nativeMap) {
1489
1500
  return new Promise((resolve, reject) => {
1490
- try {
1491
- const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
1492
- if (!packs) {
1493
- reject('No packs found or Mapbox not ready yet');
1494
- return;
1495
- }
1496
- const regions = [];
1497
- for (let i = 0; i < packs.count; i++) {
1498
- const pack = packs.objectAtIndex(i);
1499
- const region = pack.region;
1500
- const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
1501
- regions.push({
1502
- name: userInfo.objectForKey('name'),
1503
- style: '' + region.styleURL,
1504
- minZoom: region.minimumZoomLevel,
1505
- maxZoom: region.maximumZoomLevel,
1506
- bounds: {
1507
- north: region.bounds.ne.latitude,
1508
- east: region.bounds.ne.longitude,
1509
- south: region.bounds.sw.latitude,
1510
- west: region.bounds.sw.longitude
1511
- }
1512
- });
1501
+ const theMap = nativeMap || this._mapboxViewInstance;
1502
+ const points = options.points;
1503
+ if (points === undefined) {
1504
+ reject("Please set the 'points' parameter");
1505
+ return;
1506
+ }
1507
+ const coordinateArray = [];
1508
+ points.forEach((point) => coordinateArray.push([point.lng, point.lat]));
1509
+ const polygonID = `polygon_${options.id || new Date().getTime()}`;
1510
+ if (theMap.style.sourceWithIdentifier(polygonID)) {
1511
+ reject("Remove the polygon with this id first with 'removePolygons': " + polygonID);
1512
+ return;
1513
+ }
1514
+ const geoJSON = `{
1515
+ "type": "FeatureCollection",
1516
+ "features": [
1517
+ {
1518
+ "id": ${JSON.stringify(polygonID)},
1519
+ "type": "Feature",
1520
+ "properties": {
1521
+ },
1522
+ "geometry": {
1523
+ "type": "Polygon",
1524
+ "coordinates": [${JSON.stringify(coordinateArray)}]
1525
+ }
1513
1526
  }
1514
- resolve(regions);
1527
+ ]
1528
+ }`;
1529
+ const geoDataStr = NSString.stringWithString(geoJSON);
1530
+ const geoData = geoDataStr.dataUsingEncoding(NSUTF8StringEncoding);
1531
+ const geoDataBase64Enc = geoData.base64EncodedStringWithOptions(0);
1532
+ const geo = NSData.alloc().initWithBase64EncodedStringOptions(geoDataBase64Enc, null);
1533
+ const shape = MGLShape.shapeWithDataEncodingError(geo, NSUTF8StringEncoding);
1534
+ const source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(polygonID, shape, null);
1535
+ theMap.style.addSource(source);
1536
+ if (options.strokeColor || options.strokeWidth || options.strokeOpacity) {
1537
+ const strokeLayer = MGLLineStyleLayer.alloc().initWithIdentifierSource(polygonID + '_stroke', source);
1538
+ strokeLayer.lineColor = NSExpression.expressionForConstantValue(!options.strokeColor ? UIColor.blackColor : options.strokeColor instanceof Color ? options.strokeColor.ios : new Color(options.strokeColor).ios);
1539
+ strokeLayer.lineWidth = NSExpression.expressionForConstantValue(options.strokeWidth || 5);
1540
+ strokeLayer.lineOpacity = NSExpression.expressionForConstantValue(options.strokeOpacity === undefined ? 1 : options.strokeOpacity);
1541
+ theMap.style.addLayer(strokeLayer);
1542
+ }
1543
+ const layer = MGLFillStyleLayer.alloc().initWithIdentifierSource(polygonID, source);
1544
+ layer.fillColor = NSExpression.expressionForConstantValue(!options.fillColor ? UIColor.blackColor : options.fillColor instanceof Color ? options.fillColor.ios : new Color(options.fillColor).ios);
1545
+ layer.fillOpacity = NSExpression.expressionForConstantValue(options.fillOpacity === undefined ? 1 : options.fillOpacity);
1546
+ theMap.style.addLayer(layer);
1547
+ resolve();
1548
+ });
1549
+ }
1550
+ addPolyline(options, nativeMap) {
1551
+ return new Promise((resolve, reject) => {
1552
+ const theMap = nativeMap || this._mapboxViewInstance;
1553
+ const points = options.points;
1554
+ if (points === undefined) {
1555
+ reject("Please set the 'points' parameter");
1556
+ return;
1515
1557
  }
1516
- catch (ex) {
1517
- if (Trace.isEnabled()) {
1518
- CLog(CLogTypes.info, 'Error in mapbox.listOfflineRegions: ' + ex);
1519
- }
1520
- reject(ex);
1558
+ const coordinateArray = [];
1559
+ points.forEach((point) => coordinateArray.push([point.lng, point.lat]));
1560
+ const polylineID = 'polyline_' + (options.id || new Date().getTime());
1561
+ if (theMap.style.sourceWithIdentifier(polylineID)) {
1562
+ reject("Remove the polyline with this id first with 'removePolylines': " + polylineID);
1563
+ return;
1521
1564
  }
1565
+ const geoJSON = `{"type": "FeatureCollection", "features": [{"type": "Feature","properties": {},"geometry": {"type": "LineString", "coordinates": ${JSON.stringify(coordinateArray)}}}]}`;
1566
+ const geoDataStr = NSString.stringWithString(geoJSON);
1567
+ const geoData = geoDataStr.dataUsingEncoding(NSUTF8StringEncoding);
1568
+ const geoDataBase64Enc = geoData.base64EncodedStringWithOptions(0);
1569
+ const geo = NSData.alloc().initWithBase64EncodedStringOptions(geoDataBase64Enc, null);
1570
+ const shape = MGLShape.shapeWithDataEncodingError(geo, NSUTF8StringEncoding);
1571
+ const source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(polylineID, shape, null);
1572
+ theMap.style.addSource(source);
1573
+ const layer = MGLLineStyleLayer.alloc().initWithIdentifierSource(polylineID, source);
1574
+ layer.lineColor = NSExpression.expressionForConstantValue(!options.color ? UIColor.blackColor : options.color instanceof Color ? options.color.ios : new Color(options.color).ios);
1575
+ layer.lineWidth = NSExpression.expressionForConstantValue(options.width || 5);
1576
+ layer.lineOpacity = NSExpression.expressionForConstantValue(options.opacity === undefined ? 1 : options.opacity);
1577
+ theMap.style.addLayer(layer);
1578
+ resolve();
1522
1579
  });
1523
1580
  }
1524
- deleteOfflineRegion(options) {
1581
+ removePolyById(theMap, id) {
1582
+ let layer = theMap.style.layerWithIdentifier(id);
1583
+ if (layer !== null) {
1584
+ theMap.style.removeLayer(layer);
1585
+ }
1586
+ layer = theMap.style.layerWithIdentifier(id + '_stroke');
1587
+ if (layer !== null) {
1588
+ theMap.style.removeLayer(layer);
1589
+ }
1590
+ const source = theMap.style.sourceWithIdentifier(id);
1591
+ if (source !== null) {
1592
+ theMap.style.removeSource(source);
1593
+ }
1594
+ }
1595
+ removePolys(polyType, ids, nativeMap) {
1596
+ return new Promise((resolve) => {
1597
+ const theMap = nativeMap || this._mapboxViewInstance;
1598
+ ids.forEach((id) => this.removePolyById(theMap, polyType + id));
1599
+ resolve();
1600
+ });
1601
+ }
1602
+ removePolygons(ids, nativeMap) {
1603
+ return this.removePolys('polygon_', ids, nativeMap);
1604
+ }
1605
+ removePolylines(ids, nativeMap) {
1606
+ return this.removePolys('polyline_', ids, nativeMap);
1607
+ }
1608
+ animateCamera(options, nativeMap) {
1525
1609
  return new Promise((resolve, reject) => {
1526
1610
  try {
1527
- if (!options || !options.name) {
1528
- reject("Pass in the 'name' param");
1529
- return;
1611
+ const theMap = nativeMap || this._mapboxViewInstance;
1612
+ let cam;
1613
+ if (options.bounds) {
1614
+ const padding = options.padding || 0;
1615
+ const insets = {
1616
+ top: padding,
1617
+ left: padding,
1618
+ bottom: padding,
1619
+ right: padding
1620
+ };
1621
+ const bounds = {
1622
+ sw: CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west),
1623
+ ne: CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east)
1624
+ };
1625
+ cam = theMap.cameraThatFitsCoordinateBoundsEdgePadding(bounds, insets);
1530
1626
  }
1531
- const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
1532
- let found = false;
1533
- for (let i = 0; i < packs.count; i++) {
1534
- const pack = packs.objectAtIndex(i);
1535
- const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
1536
- const name = userInfo.objectForKey('name');
1537
- if (name === options.name) {
1538
- found = true;
1539
- MGLOfflineStorage.sharedOfflineStorage.removePackWithCompletionHandler(pack, (error) => {
1540
- if (error) {
1541
- reject(error.localizedFailureReason);
1542
- }
1543
- else {
1544
- resolve();
1545
- }
1546
- });
1627
+ else {
1628
+ const target = options.target;
1629
+ if (target === undefined) {
1630
+ reject("Please set the 'target' parameter");
1631
+ return;
1547
1632
  }
1633
+ cam = theMap.camera;
1634
+ cam.centerCoordinate = CLLocationCoordinate2DMake(target.lat, target.lng);
1548
1635
  }
1549
- if (!found) {
1550
- reject('Region not found');
1636
+ if (options.altitude) {
1637
+ cam.altitude = options.altitude;
1638
+ }
1639
+ if (options.bearing) {
1640
+ cam.heading = options.bearing;
1641
+ }
1642
+ if (options.tilt) {
1643
+ cam.pitch = options.tilt;
1551
1644
  }
1645
+ if (options.zoomLevel && options.target) {
1646
+ cam.altitude = MGLAltitudeForZoomLevel(options.zoomLevel, cam.pitch, options.target.lat, theMap.frame.size);
1647
+ }
1648
+ const durationMs = options.duration ? options.duration : 10000;
1649
+ theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
1650
+ setTimeout(() => {
1651
+ resolve();
1652
+ }, durationMs);
1552
1653
  }
1553
1654
  catch (ex) {
1554
1655
  if (Trace.isEnabled()) {
1555
- CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
1656
+ CLog(CLogTypes.info, 'Error in mapbox.animateCamera: ' + ex);
1556
1657
  }
1557
1658
  reject(ex);
1558
1659
  }
1559
1660
  });
1560
1661
  }
1561
- addExtrusion(options, nativeMap) {
1662
+ setOnMapClickListener(listener, nativeMap) {
1562
1663
  return new Promise((resolve, reject) => {
1563
1664
  try {
1564
1665
  const theMap = nativeMap || this._mapboxViewInstance;
@@ -1566,17 +1667,26 @@ export class Mapbox extends MapboxCommon {
1566
1667
  reject('No map has been loaded');
1567
1668
  return;
1568
1669
  }
1670
+ theMap['mapTapHandler'] = MapTapHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
1671
+ const tapGestureRecognizer = UITapGestureRecognizer.alloc().initWithTargetAction(theMap['mapTapHandler'], 'tap');
1672
+ for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1673
+ const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1674
+ if (recognizer instanceof UITapGestureRecognizer) {
1675
+ tapGestureRecognizer.requireGestureRecognizerToFail(recognizer);
1676
+ }
1677
+ }
1678
+ theMap.addGestureRecognizer(tapGestureRecognizer);
1569
1679
  resolve();
1570
1680
  }
1571
1681
  catch (ex) {
1572
1682
  if (Trace.isEnabled()) {
1573
- CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
1683
+ CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
1574
1684
  }
1575
1685
  reject(ex);
1576
1686
  }
1577
1687
  });
1578
1688
  }
1579
- updateSource(id, options, nativeMap) {
1689
+ setOnMapLongClickListener(listener, nativeMap) {
1580
1690
  return new Promise((resolve, reject) => {
1581
1691
  try {
1582
1692
  const theMap = nativeMap || this._mapboxViewInstance;
@@ -1584,159 +1694,88 @@ export class Mapbox extends MapboxCommon {
1584
1694
  reject('No map has been loaded');
1585
1695
  return;
1586
1696
  }
1587
- const source = theMap.style.sourceWithIdentifier(id);
1588
- if (!source) {
1589
- reject('Source does not exists: ' + id);
1590
- return;
1591
- }
1592
- switch (options.type) {
1593
- case 'geojson':
1594
- const content = NSString.stringWithString(JSON.stringify(options.data));
1595
- const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
1596
- const geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
1597
- source.shape = geoJsonShape;
1598
- break;
1599
- default:
1600
- reject('Invalid source type: ' + options['type']);
1601
- return;
1697
+ theMap['mapLongPressHandler'] = MapLongPressHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
1698
+ const longPressGestureRecognizer = UILongPressGestureRecognizer.alloc().initWithTargetAction(theMap['mapLongPressHandler'], 'longPress');
1699
+ for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1700
+ const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1701
+ if (recognizer instanceof UILongPressGestureRecognizer) {
1702
+ longPressGestureRecognizer.requireGestureRecognizerToFail(recognizer);
1703
+ }
1602
1704
  }
1705
+ theMap.addGestureRecognizer(longPressGestureRecognizer);
1706
+ resolve();
1603
1707
  }
1604
1708
  catch (ex) {
1605
1709
  if (Trace.isEnabled()) {
1606
- CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
1710
+ CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
1607
1711
  }
1608
1712
  reject(ex);
1609
1713
  }
1610
1714
  });
1611
1715
  }
1612
- addSource(id, options, nativeMap) {
1716
+ setOnScrollListener(listener, nativeMap) {
1613
1717
  return new Promise((resolve, reject) => {
1614
1718
  try {
1615
1719
  const theMap = nativeMap || this._mapboxViewInstance;
1616
- let source;
1617
1720
  if (!theMap) {
1618
1721
  reject('No map has been loaded');
1619
1722
  return;
1620
1723
  }
1621
- if (theMap.style.sourceWithIdentifier(id)) {
1622
- reject('Source exists: ' + id);
1623
- return;
1724
+ if (theMap['mapPanHandler'] === undefined) {
1725
+ theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 2, theMap);
1624
1726
  }
1625
- switch (options.type) {
1626
- case 'vector': {
1627
- if (options.url) {
1628
- source = MGLVectorTileSource.alloc().initWithIdentifierConfigurationURL(id, NSURL.URLWithString(options.url));
1629
- }
1630
- else {
1631
- const sourceOptions = {};
1632
- if (options.minzoom !== undefined) {
1633
- sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
1634
- }
1635
- if (options.maxzoom !== undefined) {
1636
- sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
1637
- }
1638
- if (options.scheme) {
1639
- switch (options.scheme) {
1640
- case 'xyz':
1641
- sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
1642
- break;
1643
- case 'tms':
1644
- sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
1645
- break;
1646
- default:
1647
- throw new Error('Unknown raster tile scheme.');
1648
- }
1649
- }
1650
- if (options.bounds) {
1651
- sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
1652
- sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
1653
- ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
1654
- });
1655
- }
1656
- source = MGLVectorTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
1657
- }
1658
- break;
1659
- }
1660
- case 'geojson':
1661
- if (theMap.style.sourceWithIdentifier(id)) {
1662
- reject("Remove the layer with this id first with 'removeLayer': " + id);
1663
- return;
1664
- }
1665
- let geoJsonShape;
1666
- if (options.data) {
1667
- const content = NSString.stringWithString(JSON.stringify(options.data));
1668
- const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
1669
- geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
1670
- }
1671
- const sourceOptions = {};
1672
- if (options.minzoom !== undefined) {
1673
- sourceOptions[MGLShapeSourceOptionMinimumZoomLevel] = options.minzoom;
1674
- }
1675
- if (options.maxzoom !== undefined) {
1676
- sourceOptions[MGLShapeSourceOptionMaximumZoomLevel] = options.maxzoom;
1677
- }
1678
- if (options.cluster) {
1679
- sourceOptions[MGLShapeSourceOptionClustered] = true;
1680
- sourceOptions[MGLShapeSourceOptionClusterRadius] = options.cluster.radius || 40;
1681
- sourceOptions[MGLShapeSourceOptionMaximumZoomLevelForClustering] = options.cluster.maxZoom || 13;
1682
- }
1683
- source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, geoJsonShape, sourceOptions);
1684
- break;
1685
- case 'raster': {
1686
- const sourceOptions = {
1687
- [MGLTileSourceOptionTileSize]: options.tileSize || 256
1688
- };
1689
- if (options.minzoom !== undefined) {
1690
- sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
1691
- }
1692
- if (options.maxzoom !== undefined) {
1693
- sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
1694
- }
1695
- if (options.scheme) {
1696
- switch (options.scheme || 'xyz') {
1697
- case 'xyz':
1698
- sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
1699
- break;
1700
- case 'tms':
1701
- sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
1702
- break;
1703
- default:
1704
- throw new Error('Unknown raster tile scheme.');
1705
- }
1706
- }
1707
- if (options.bounds) {
1708
- sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
1709
- sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
1710
- ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
1711
- });
1712
- }
1713
- source = MGLRasterTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
1727
+ else {
1728
+ theMap['mapPanHandler'].addListener(2, listener);
1729
+ }
1730
+ for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1731
+ const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1732
+ if (recognizer instanceof UIPanGestureRecognizer) {
1733
+ recognizer.addTargetAction(theMap['mapPanHandler'], 'pan');
1714
1734
  break;
1715
1735
  }
1716
- default:
1717
- reject('Invalid source type: ' + options['type']);
1718
- return;
1719
1736
  }
1720
- if (!source) {
1721
- const ex = 'No source to add';
1722
- if (Trace.isEnabled()) {
1723
- CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
1724
- }
1725
- reject(ex);
1737
+ resolve();
1738
+ }
1739
+ catch (ex) {
1740
+ if (Trace.isEnabled()) {
1741
+ CLog(CLogTypes.info, 'Error in mapbox.setOnScrollListener: ' + ex);
1742
+ }
1743
+ reject(ex);
1744
+ }
1745
+ });
1746
+ }
1747
+ setOnMoveBeginListener(listener, nativeMap) {
1748
+ return new Promise((resolve, reject) => {
1749
+ try {
1750
+ const theMap = nativeMap || this._mapboxViewInstance;
1751
+ if (!theMap) {
1752
+ reject('No map has been loaded');
1726
1753
  return;
1727
1754
  }
1728
- theMap.style.addSource(source);
1755
+ if (theMap['mapPanHandler'] === undefined) {
1756
+ theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 1, theMap);
1757
+ }
1758
+ else {
1759
+ theMap['mapPanHandler'].addListener(1, listener);
1760
+ }
1761
+ for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1762
+ const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1763
+ if (recognizer instanceof UIPanGestureRecognizer) {
1764
+ recognizer.addTargetAction(theMap['mapPanHandler'], 'panBegin');
1765
+ break;
1766
+ }
1767
+ }
1729
1768
  resolve();
1730
1769
  }
1731
1770
  catch (ex) {
1732
1771
  if (Trace.isEnabled()) {
1733
- CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
1772
+ CLog(CLogTypes.info, 'Error in mapbox.setOnMoveBeginListener: ' + ex);
1734
1773
  }
1735
1774
  reject(ex);
1736
1775
  }
1737
1776
  });
1738
1777
  }
1739
- removeSource(id, nativeMap) {
1778
+ setOnMoveEndListener(listener, nativeMap) {
1740
1779
  return new Promise((resolve, reject) => {
1741
1780
  try {
1742
1781
  const theMap = nativeMap || this._mapboxViewInstance;
@@ -1744,109 +1783,246 @@ export class Mapbox extends MapboxCommon {
1744
1783
  reject('No map has been loaded');
1745
1784
  return;
1746
1785
  }
1747
- const source = theMap.style.sourceWithIdentifier(id);
1748
- if (!source) {
1749
- reject('Source does not exist');
1750
- return;
1786
+ if (theMap['mapPanHandler'] === undefined) {
1787
+ theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 3, theMap);
1788
+ }
1789
+ else {
1790
+ theMap['mapPanHandler'].addListener(3, listener);
1791
+ }
1792
+ for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1793
+ const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1794
+ if (recognizer instanceof UIPanGestureRecognizer) {
1795
+ recognizer.addTargetAction(theMap['mapPanHandler'], 'panEnd');
1796
+ break;
1797
+ }
1751
1798
  }
1752
- theMap.style.removeSource(source);
1753
1799
  resolve();
1754
1800
  }
1755
1801
  catch (ex) {
1756
1802
  if (Trace.isEnabled()) {
1757
- CLog(CLogTypes.info, 'Error in mapbox.removeSource: ' + ex);
1803
+ CLog(CLogTypes.info, 'Error in mapbox.setOnMoveEndListener: ' + ex);
1758
1804
  }
1759
1805
  reject(ex);
1760
1806
  }
1761
1807
  });
1762
1808
  }
1763
- async addLayer(style, belowLayerId, nativeMapView) {
1764
- const theMap = nativeMapView || this._mapboxViewInstance;
1765
- let source = null;
1766
- if (typeof style.source != 'string') {
1767
- await this.addSource(style.id + '_source', style.source);
1768
- source = theMap.style.sourceWithIdentifier(style.id + '_source');
1809
+ setOnFlingListener(listener, nativeMap) {
1810
+ return Promise.reject("'setOnFlingListener' is not supported on iOS");
1811
+ }
1812
+ async setOnCameraMoveListener(listener, nativeMap) {
1813
+ const theMap = nativeMap || this._mapboxViewInstance;
1814
+ if (theMap) {
1815
+ theMap.delegate.setCameraChangedListener(listener);
1769
1816
  }
1770
1817
  else {
1771
- source = theMap.style.sourceWithIdentifier(style.source);
1772
- }
1773
- const layer = await LayerFactory.createLayer(style, source);
1774
- if (belowLayerId) {
1775
- const belowlayer = theMap.style.layerWithIdentifier(belowLayerId);
1776
- if (belowlayer) {
1777
- theMap.style.insertLayerBelowLayer(layer.getNativeInstance(), belowlayer);
1778
- return;
1779
- }
1818
+ return Promise.reject('No map has been loaded');
1780
1819
  }
1781
- theMap.style.addLayer(layer.getNativeInstance());
1782
1820
  }
1783
- async removeLayer(id, nativeMapViewInstance) {
1784
- const theMap = nativeMapViewInstance || this._mapboxViewInstance;
1785
- if (Trace.isEnabled()) {
1786
- CLog(CLogTypes.info, "Mapbox::removeLayer(): attempting to remove layer '" + id + "'");
1787
- }
1788
- const layer = theMap.style.layerWithIdentifier(id);
1789
- if (Trace.isEnabled()) {
1790
- CLog(CLogTypes.info, 'Mapbox:removeLayer(): got layer object: ', layer);
1791
- }
1792
- if (!layer) {
1793
- throw new Error("Layer '" + id + "' not found when attempting to remove it.");
1821
+ setOnCameraMoveCancelListener(listener, nativeMap) {
1822
+ return Promise.reject("'setOnCameraMoveCancelListener' not currently supported on iOS");
1823
+ }
1824
+ async setOnCameraIdleListener(listener, nativeMap) {
1825
+ const theMap = nativeMap || this._mapboxViewInstance;
1826
+ if (theMap) {
1827
+ theMap.delegate.setCameraIdledListener(listener);
1794
1828
  }
1795
- theMap.style.removeLayer(layer);
1796
- if (Trace.isEnabled()) {
1797
- CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer ' + id);
1829
+ else {
1830
+ return Promise.reject('No map has been loaded');
1798
1831
  }
1799
1832
  }
1800
- async addLinePoint(id, lnglat, sourceId, nativeMapView) {
1801
- const theMap = nativeMapView || this._mapboxViewInstance;
1802
- const sId = !!sourceId ? sourceId : id + '_source';
1803
- const lineSource = theMap.style.sourceWithIdentifier(sId);
1804
- if (!lineSource) {
1805
- throw new Error(`no source found with id: ${sId}`);
1806
- }
1807
- try {
1808
- const lineFeatures = lineSource.featuresMatchingPredicate(FilterParser.parseJson(['==', '$type', 'LineString']));
1809
- if (lineFeatures.count === 0) {
1810
- throw new Error('no line string feature found');
1833
+ getViewport(nativeMap) {
1834
+ return new Promise((resolve, reject) => {
1835
+ try {
1836
+ const theMap = nativeMap || this._mapboxViewInstance;
1837
+ if (!theMap) {
1838
+ reject('No map has been loaded');
1839
+ return;
1840
+ }
1841
+ const visibleBounds = theMap.visibleCoordinateBounds;
1842
+ const bounds = {
1843
+ north: visibleBounds.ne.latitude,
1844
+ east: visibleBounds.ne.longitude,
1845
+ south: visibleBounds.sw.latitude,
1846
+ west: visibleBounds.sw.longitude
1847
+ };
1848
+ resolve({
1849
+ bounds,
1850
+ zoomLevel: theMap.zoomLevel
1851
+ });
1852
+ }
1853
+ catch (ex) {
1854
+ if (Trace.isEnabled()) {
1855
+ CLog(CLogTypes.info, 'Error in mapbox.getViewport: ' + ex);
1856
+ }
1857
+ reject(ex);
1858
+ }
1859
+ });
1860
+ }
1861
+ setViewport(options, nativeMap) {
1862
+ return new Promise((resolve, reject) => {
1863
+ try {
1864
+ const theMap = nativeMap || this._mapboxViewInstance;
1865
+ if (!theMap) {
1866
+ reject('No map has been loaded');
1867
+ return;
1868
+ }
1869
+ const bounds = {
1870
+ sw: CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west),
1871
+ ne: CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east)
1872
+ };
1873
+ const animated = options.animated === undefined || options.animated;
1874
+ const padding = options.padding !== undefined ? { top: options.padding, left: options.padding, bottom: options.padding, right: options.padding } : { top: 25, left: 25, bottom: 25, right: 25 };
1875
+ theMap.setVisibleCoordinateBoundsEdgePaddingAnimated(bounds, padding, animated);
1876
+ resolve();
1877
+ }
1878
+ catch (ex) {
1879
+ if (Trace.isEnabled()) {
1880
+ CLog(CLogTypes.info, 'Error in mapbox.setViewport: ' + ex);
1881
+ }
1882
+ reject(ex);
1883
+ }
1884
+ });
1885
+ }
1886
+ downloadOfflineRegion(options) {
1887
+ return new Promise((resolve, reject) => {
1888
+ try {
1889
+ const styleURL = _getMapStyle(options.style);
1890
+ const swCoordinate = CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west);
1891
+ const neCoordinate = CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east);
1892
+ const bounds = {
1893
+ sw: swCoordinate,
1894
+ ne: neCoordinate
1895
+ };
1896
+ const region = MGLTilePyramidOfflineRegion.alloc().initWithStyleURLBoundsFromZoomLevelToZoomLevel(styleURL, bounds, options.minZoom, options.maxZoom);
1897
+ if (options.accessToken) {
1898
+ MGLAccountManager.accessToken = options.accessToken;
1899
+ }
1900
+ if (options.onProgress) {
1901
+ _addObserver(MGLOfflinePackProgressChangedNotification, (notification) => {
1902
+ const offlinePack = notification.object;
1903
+ const offlinePackProgress = offlinePack.progress;
1904
+ const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1905
+ const complete = offlinePackProgress.countOfResourcesCompleted === offlinePackProgress.countOfResourcesExpected;
1906
+ options.onProgress({
1907
+ name: userInfo.objectForKey('name'),
1908
+ completed: offlinePackProgress.countOfResourcesCompleted,
1909
+ expected: offlinePackProgress.countOfResourcesExpected,
1910
+ percentage: Math.round((offlinePackProgress.countOfResourcesCompleted / offlinePackProgress.countOfResourcesExpected) * 10000) / 100,
1911
+ complete
1912
+ });
1913
+ if (complete) {
1914
+ resolve();
1915
+ }
1916
+ });
1917
+ }
1918
+ _addObserver(MGLOfflinePackErrorNotification, (notification) => {
1919
+ const offlinePack = notification.object;
1920
+ const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1921
+ const error = notification.userInfo[MGLOfflinePackUserInfoKeyError];
1922
+ reject({
1923
+ name: userInfo.objectForKey('name'),
1924
+ error: 'Download error. ' + error
1925
+ });
1926
+ });
1927
+ _addObserver(MGLOfflinePackMaximumMapboxTilesReachedNotification, (notification) => {
1928
+ const offlinePack = notification.object;
1929
+ const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1930
+ const maximumCount = notification.userInfo[MGLOfflinePackUserInfoKeyMaximumCount];
1931
+ console.log(`Offline region '${userInfo.objectForKey('name')}' reached the tile limit of ${maximumCount}`);
1932
+ });
1933
+ const userInfo = { name: options.name };
1934
+ const context = NSKeyedArchiver.archivedDataWithRootObject(userInfo);
1935
+ MGLOfflineStorage.sharedOfflineStorage.addPackForRegionWithContextCompletionHandler(region, context, (pack, error) => {
1936
+ if (error) {
1937
+ reject(error.localizedFailureReason);
1938
+ }
1939
+ else {
1940
+ pack.resume();
1941
+ }
1942
+ });
1943
+ }
1944
+ catch (ex) {
1945
+ if (Trace.isEnabled()) {
1946
+ CLog(CLogTypes.info, 'Error in mapbox.downloadOfflineRegion: ' + ex);
1947
+ }
1948
+ reject(ex);
1949
+ }
1950
+ });
1951
+ }
1952
+ listOfflineRegions(options) {
1953
+ return new Promise((resolve, reject) => {
1954
+ try {
1955
+ const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
1956
+ if (!packs) {
1957
+ reject('No packs found or Mapbox not ready yet');
1958
+ return;
1959
+ }
1960
+ const regions = [];
1961
+ for (let i = 0; i < packs.count; i++) {
1962
+ const pack = packs.objectAtIndex(i);
1963
+ const region = pack.region;
1964
+ const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
1965
+ regions.push({
1966
+ name: userInfo.objectForKey('name'),
1967
+ style: '' + region.styleURL,
1968
+ minZoom: region.minimumZoomLevel,
1969
+ maxZoom: region.maximumZoomLevel,
1970
+ bounds: {
1971
+ north: region.bounds.ne.latitude,
1972
+ east: region.bounds.ne.longitude,
1973
+ south: region.bounds.sw.latitude,
1974
+ west: region.bounds.sw.longitude
1975
+ }
1976
+ });
1977
+ }
1978
+ resolve(regions);
1979
+ }
1980
+ catch (ex) {
1981
+ if (Trace.isEnabled()) {
1982
+ CLog(CLogTypes.info, 'Error in mapbox.listOfflineRegions: ' + ex);
1983
+ }
1984
+ reject(ex);
1811
1985
  }
1812
- const lineFeature = lineFeatures.objectAtIndex(0);
1813
- const newCoord = CLLocationCoordinate2DMake(lnglat[1], lnglat[0]);
1814
- const newCoordPointer = new interop.Reference(newCoord);
1815
- lineFeature.appendCoordinatesCount(newCoordPointer, 1);
1816
- lineSource.shape = lineFeature;
1817
- }
1818
- catch (error) {
1819
- console.log(error);
1820
- throw error;
1821
- }
1822
- }
1823
- addGeoJsonClustered(options, nativeMapViewInstance) {
1824
- throw new Error('Method not implemented.');
1986
+ });
1825
1987
  }
1826
- trackUser(options, nativeMap) {
1988
+ deleteOfflineRegion(options) {
1827
1989
  return new Promise((resolve, reject) => {
1828
1990
  try {
1829
- const theMap = nativeMap || this._mapboxViewInstance;
1830
- if (!theMap) {
1831
- reject('No map has been loaded');
1991
+ if (!options || (!options.id && !options.name)) {
1992
+ reject("Pass in the 'id' or 'name' param");
1832
1993
  return;
1833
1994
  }
1834
- if (!theMap.showsUserLocation) {
1835
- reject('The map is not currently showing the user location');
1836
- return;
1995
+ const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
1996
+ let found = false;
1997
+ for (let i = 0; i < packs.count; i++) {
1998
+ const pack = packs.objectAtIndex(i);
1999
+ const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
2000
+ const regionId = options.id ? userInfo.objectForKey('id') : userInfo.objectForKey('name');
2001
+ if (regionId === (options.id || options.name)) {
2002
+ found = true;
2003
+ MGLOfflineStorage.sharedOfflineStorage.removePackWithCompletionHandler(pack, (error) => {
2004
+ if (error) {
2005
+ reject(error.localizedFailureReason);
2006
+ }
2007
+ else {
2008
+ resolve();
2009
+ }
2010
+ });
2011
+ }
2012
+ }
2013
+ if (!found) {
2014
+ reject('Region not found');
1837
2015
  }
1838
- theMap.setUserTrackingModeAnimated(_getTrackingMode(options.mode), options.animated !== false);
1839
- resolve();
1840
2016
  }
1841
2017
  catch (ex) {
1842
2018
  if (Trace.isEnabled()) {
1843
- CLog(CLogTypes.info, 'Error in mapbox.trackUser: ' + ex);
2019
+ CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
1844
2020
  }
1845
2021
  reject(ex);
1846
2022
  }
1847
2023
  });
1848
2024
  }
1849
- getLayer(name, nativeMap) {
2025
+ addExtrusion(options, nativeMap) {
1850
2026
  return new Promise((resolve, reject) => {
1851
2027
  try {
1852
2028
  const theMap = nativeMap || this._mapboxViewInstance;
@@ -1854,18 +2030,17 @@ export class Mapbox extends MapboxCommon {
1854
2030
  reject('No map has been loaded');
1855
2031
  return;
1856
2032
  }
1857
- const layer = theMap.style.layerWithIdentifier(name);
1858
- resolve(new Layer(layer));
2033
+ resolve();
1859
2034
  }
1860
2035
  catch (ex) {
1861
2036
  if (Trace.isEnabled()) {
1862
- CLog(CLogTypes.info, 'Error in mapbox.getLayer: ' + ex);
2037
+ CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
1863
2038
  }
1864
2039
  reject(ex);
1865
2040
  }
1866
2041
  });
1867
2042
  }
1868
- getLayers(nativeMap) {
2043
+ updateSource(id, options, nativeMap) {
1869
2044
  return new Promise((resolve, reject) => {
1870
2045
  try {
1871
2046
  const theMap = nativeMap || this._mapboxViewInstance;
@@ -1873,489 +2048,364 @@ export class Mapbox extends MapboxCommon {
1873
2048
  reject('No map has been loaded');
1874
2049
  return;
1875
2050
  }
1876
- const layers = theMap.style.layers;
1877
- const result = [];
1878
- for (let i = 0; i < layers.count; i++) {
1879
- result.push(new Layer(layers[i]));
1880
- }
1881
- resolve(result);
1882
- }
1883
- catch (ex) {
1884
- if (Trace.isEnabled()) {
1885
- CLog(CLogTypes.info, 'Error in mapbox.getLayers: ' + ex);
2051
+ const source = theMap.style.sourceWithIdentifier(id);
2052
+ if (!source) {
2053
+ reject('Source does not exists: ' + id);
2054
+ return;
1886
2055
  }
1887
- reject(ex);
1888
- }
1889
- });
1890
- }
1891
- project(data) {
1892
- const theMap = this._mapboxViewInstance;
1893
- const { x, y } = theMap.convertCoordinateToPointToView({ latitude: data.lat, longitude: data.lng }, theMap);
1894
- return { x, y };
1895
- }
1896
- }
1897
- const _addObserver = (eventName, callback) => NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(eventName, null, NSOperationQueue.mainQueue, callback);
1898
- function _downloadImage(marker) {
1899
- return new Promise((resolve, reject) => {
1900
- if (Trace.isEnabled()) {
1901
- CLog(CLogTypes.info, '>> _downloadImage');
1902
- }
1903
- if (_markerIconDownloadCache[marker.icon]) {
1904
- marker.iconDownloaded = _markerIconDownloadCache[marker.icon];
1905
- if (Trace.isEnabled()) {
1906
- CLog(CLogTypes.info, '>> marker.iconDownloaded: ' + marker.iconDownloaded);
1907
- }
1908
- resolve(marker);
1909
- return;
1910
- }
1911
- getImage(marker.icon).then((output) => {
1912
- marker.iconDownloaded = output.ios;
1913
- _markerIconDownloadCache[marker.icon] = marker.iconDownloaded;
1914
- resolve(marker);
1915
- }, (ignoredError) => {
1916
- console.log(`Download failed for ${marker.icon} with error: ${ignoredError}`);
1917
- resolve(marker);
1918
- });
1919
- });
1920
- }
1921
- const _downloadMarkerImages = (markers) => {
1922
- const iterations = [];
1923
- const result = [];
1924
- markers.forEach((marker) => {
1925
- if (marker.icon && marker.icon.startsWith('http')) {
1926
- const p = _downloadImage(marker).then((mark) => result.push(mark));
1927
- iterations.push(p);
1928
- }
1929
- else {
1930
- result.push(marker);
1931
- }
1932
- });
1933
- return Promise.all(iterations).then(() => result);
1934
- };
1935
- var MGLMapViewDelegateImpl = /** @class */ (function (_super) {
1936
- __extends(MGLMapViewDelegateImpl, _super);
1937
- function MGLMapViewDelegateImpl() {
1938
- return _super !== null && _super.apply(this, arguments) || this;
1939
- }
1940
- MGLMapViewDelegateImpl.new = function () {
1941
- return _super.new.call(this);
1942
- };
1943
- /**
1944
- * initialize with the mapReady callback
1945
- */
1946
- MGLMapViewDelegateImpl.prototype.initWithCallback = function (mapLoadedCallback) {
1947
- if (Trace.isEnabled()) {
1948
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::initWithCallback()');
1949
- }
1950
- this.mapLoadedCallback = mapLoadedCallback;
1951
- return this;
1952
- };
1953
- /**
1954
- * set a reference to the mapboxAPI instance
1955
- */
1956
- MGLMapViewDelegateImpl.prototype.setMapboxApi = function (api) {
1957
- this.mapboxApi = api;
1958
- };
1959
- /**
1960
- * set the user location click listener callback
1961
- */
1962
- MGLMapViewDelegateImpl.prototype.setUserLocationClickListener = function (callback) {
1963
- this.userLocationClickListener = callback;
1964
- };
1965
- /**
1966
- * set the user location click listener callback
1967
- */
1968
- MGLMapViewDelegateImpl.prototype.setUserLocationChangedistener = function (callback) {
1969
- this.userLocationChangedListener = callback;
1970
- };
1971
- /**
1972
- * set user location marker modes
1973
- */
1974
- MGLMapViewDelegateImpl.prototype.changeUserLocationRenderMode = function (userLocationRenderMode) {
1975
- this.userLocationAnnotationView.changeUserLocationRenderMode(userLocationRenderMode);
1976
- };
1977
- /**
1978
- * set the camera changd listener callback
1979
- */
1980
- MGLMapViewDelegateImpl.prototype.setCameraChangedListener = function (callback) {
1981
- this.cameraChangedListener = callback;
1982
- };
1983
- /**
1984
- * set the camera idled listener callback
1985
- */
1986
- MGLMapViewDelegateImpl.prototype.setCameraIdledListener = function (callback) {
1987
- this.cameraIdledListener = callback;
1988
- };
1989
- /**
1990
- * set style loaded callback.
1991
- *
1992
- * set an optional callback to be invoked when a style set with
1993
- * setMapStyle() is finished loading
1994
- *
1995
- * @param {function} callback function with loaded style as parameter.
1996
- *
1997
- * @see Mapbox:setMapStyle()
1998
- */
1999
- MGLMapViewDelegateImpl.prototype.setStyleLoadedCallback = function (callback) {
2000
- this.styleLoadedCallback = callback;
2001
- };
2002
- /**
2003
- * map ready callback
2004
- */
2005
- MGLMapViewDelegateImpl.prototype.mapViewDidFinishLoadingMap = function (mapView) {
2006
- if (Trace.isEnabled()) {
2007
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingMap(): top');
2008
- }
2009
- if (this.mapLoadedCallback !== undefined) {
2010
- this.mapLoadedCallback(mapView);
2011
- // this should be fired only once, but it's also fired when the style changes, so just remove the callback
2012
- this.mapLoadedCallback = undefined;
2013
- }
2014
- };
2015
- MGLMapViewDelegateImpl.prototype.mapViewDidFinishRenderingMapFullyRendered = function (mapView, fullyRendered) {
2016
- if (Trace.isEnabled()) {
2017
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishRenderingMapFullyRendered(): rendered is:', fullyRendered);
2018
- }
2019
- };
2020
- /**
2021
- * Callback when the style has been loaded.
2022
- *
2023
- * Based on my testing, it looks like this callback is invoked multiple times.
2024
- *
2025
- * @see Mapbox:setMapStyle()
2026
- *
2027
- * @link https://mapbox.github.io/mapbox-gl-native/macos/0.3.0/Protocols/MGLMapViewDelegate.html#/c:objc(pl)MGLMapViewDelegate(im)mapView:didFinishLoadingStyle:
2028
- */
2029
- MGLMapViewDelegateImpl.prototype.mapViewDidFinishLoadingStyle = function (mapView, style) {
2030
- if (Trace.isEnabled()) {
2031
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingStyle(): callback called.');
2032
- }
2033
- if (this.styleLoadedCallback !== undefined) {
2034
- this.styleLoadedCallback(mapView, style);
2035
- // to avoid multiple calls. This is only invoked from setMapStyle().
2036
- this.styleLoadedCallback = undefined;
2037
- }
2038
- };
2039
- /**
2040
- * disable the default user location callout
2041
- *
2042
- * This took forever to find. The default iOS click handler for the user location
2043
- * marker is about useless. It just displays "You Are Here". The examples do not
2044
- * show how to disable it.
2045
- */
2046
- MGLMapViewDelegateImpl.prototype.mapViewAnnotationCanShowCallout = function (mapView, annotation) {
2047
- if (annotation.isKindOfClass(MGLUserLocation.class())) {
2048
- return false;
2049
- }
2050
- else {
2051
- return true;
2052
- }
2053
- };
2054
- MGLMapViewDelegateImpl.prototype.mapViewDidFailLoadingMapWithError = function (mapView, error) {
2055
- if (Trace.isEnabled()) {
2056
- CLog(CLogTypes.info, 'mapViewDidFailLoadingMapWithError: ' + error);
2057
- }
2058
- };
2059
- MGLMapViewDelegateImpl.prototype.mapViewDidChangeUserTrackingModeAnimated = function (mapView, mode, animated) {
2060
- if (Trace.isEnabled()) {
2061
- CLog(CLogTypes.info, 'mapViewDidChangeUserTrackingModeAnimated: ' + mode);
2062
- }
2063
- };
2064
- /**
2065
- * fired when the marker icon is about to be rendered - return null for the default icon
2066
- */
2067
- MGLMapViewDelegateImpl.prototype.mapViewImageForAnnotation = function (mapView, annotation) {
2068
- var cachedMarker = this.getTappedMarkerDetails(annotation);
2069
- if (cachedMarker) {
2070
- if (cachedMarker.reuseIdentifier) {
2071
- var reusedImage = mapView.dequeueReusableAnnotationImageWithIdentifier(cachedMarker.reuseIdentifier);
2072
- if (reusedImage) {
2073
- return reusedImage;
2056
+ switch (options.type) {
2057
+ case 'geojson':
2058
+ const content = NSString.stringWithString(JSON.stringify(options.data));
2059
+ const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
2060
+ const geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
2061
+ source.shape = geoJsonShape;
2062
+ break;
2063
+ default:
2064
+ reject('Invalid source type: ' + options['type']);
2065
+ return;
2074
2066
  }
2075
2067
  }
2076
- // TODO try adding .rotatesToMatchCamera = true;
2077
- // .. for instance in the mapViewDidDeselectAnnotationView / mapViewDidSelectAnnotationView / mapViewViewForAnnotation delegate
2078
- if (cachedMarker.icon) {
2079
- if (cachedMarker.icon.startsWith('res://')) {
2080
- var resourceName = cachedMarker.icon.substring('res://'.length);
2081
- var imageSource = ImageSource.fromResourceSync(resourceName);
2082
- if (imageSource === null) {
2083
- console.log("Unable to locate " + resourceName);
2084
- }
2085
- else {
2086
- cachedMarker.reuseIdentifier = cachedMarker.icon;
2087
- return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(imageSource.ios, cachedMarker.reuseIdentifier);
2088
- }
2068
+ catch (ex) {
2069
+ if (Trace.isEnabled()) {
2070
+ CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
2089
2071
  }
2090
- else if (cachedMarker.icon.startsWith('http')) {
2091
- if (cachedMarker.iconDownloaded !== null) {
2092
- cachedMarker.reuseIdentifier = cachedMarker.icon;
2093
- return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(cachedMarker.iconDownloaded, cachedMarker.reuseIdentifier);
2072
+ reject(ex);
2073
+ }
2074
+ });
2075
+ }
2076
+ addSource(id, options, nativeMap) {
2077
+ return new Promise((resolve, reject) => {
2078
+ try {
2079
+ const theMap = nativeMap || this._mapboxViewInstance;
2080
+ let source;
2081
+ if (!theMap) {
2082
+ reject('No map has been loaded');
2083
+ return;
2084
+ }
2085
+ if (theMap.style.sourceWithIdentifier(id)) {
2086
+ reject('Source exists: ' + id);
2087
+ return;
2088
+ }
2089
+ switch (options.type) {
2090
+ case 'vector': {
2091
+ if (options.url) {
2092
+ source = MGLVectorTileSource.alloc().initWithIdentifierConfigurationURL(id, NSURL.URLWithString(options.url));
2093
+ }
2094
+ else {
2095
+ const sourceOptions = {};
2096
+ if (options.minzoom !== undefined) {
2097
+ sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
2098
+ }
2099
+ if (options.maxzoom !== undefined) {
2100
+ sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
2101
+ }
2102
+ if (options.scheme) {
2103
+ switch (options.scheme) {
2104
+ case 'xyz':
2105
+ sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
2106
+ break;
2107
+ case 'tms':
2108
+ sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
2109
+ break;
2110
+ default:
2111
+ throw new Error('Unknown raster tile scheme.');
2112
+ }
2113
+ }
2114
+ if (options.bounds) {
2115
+ sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
2116
+ sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
2117
+ ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
2118
+ });
2119
+ }
2120
+ source = MGLVectorTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
2121
+ }
2122
+ break;
2123
+ }
2124
+ case 'geojson':
2125
+ if (theMap.style.sourceWithIdentifier(id)) {
2126
+ reject("Remove the layer with this id first with 'removeLayer': " + id);
2127
+ return;
2128
+ }
2129
+ let geoJsonShape;
2130
+ if (options.data) {
2131
+ const content = NSString.stringWithString(JSON.stringify(options.data));
2132
+ const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
2133
+ geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
2134
+ }
2135
+ const sourceOptions = {};
2136
+ if (options.minzoom !== undefined) {
2137
+ sourceOptions[MGLShapeSourceOptionMinimumZoomLevel] = options.minzoom;
2138
+ }
2139
+ if (options.maxzoom !== undefined) {
2140
+ sourceOptions[MGLShapeSourceOptionMaximumZoomLevel] = options.maxzoom;
2141
+ }
2142
+ if (options.cluster) {
2143
+ sourceOptions[MGLShapeSourceOptionClustered] = true;
2144
+ sourceOptions[MGLShapeSourceOptionClusterRadius] = options.cluster.radius || 40;
2145
+ sourceOptions[MGLShapeSourceOptionMaximumZoomLevelForClustering] = options.cluster.maxZoom || 13;
2146
+ if (options.cluster.properties) {
2147
+ const clusterProperties = {};
2148
+ for (const property of Object.keys(options.cluster.properties)) {
2149
+ let [operator, operand] = options.cluster.properties[property];
2150
+ if (!Array.isArray(operator)) {
2151
+ operator = [operator];
2152
+ }
2153
+ const expressions = Utils.ios.collections.jsArrayToNSArray([ExpressionParser.parseJson(operator), ExpressionParser.parseJson(operand)]);
2154
+ clusterProperties[property] = expressions;
2155
+ }
2156
+ sourceOptions[MGLShapeSourceOptionClusterProperties] = clusterProperties;
2157
+ }
2158
+ }
2159
+ source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, geoJsonShape, sourceOptions);
2160
+ break;
2161
+ case 'raster': {
2162
+ const sourceOptions = {
2163
+ [MGLTileSourceOptionTileSize]: options.tileSize || 256
2164
+ };
2165
+ if (options.minzoom !== undefined) {
2166
+ sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
2167
+ }
2168
+ if (options.maxzoom !== undefined) {
2169
+ sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
2170
+ }
2171
+ if (options.scheme) {
2172
+ switch (options.scheme || 'xyz') {
2173
+ case 'xyz':
2174
+ sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
2175
+ break;
2176
+ case 'tms':
2177
+ sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
2178
+ break;
2179
+ default:
2180
+ throw new Error('Unknown raster tile scheme.');
2181
+ }
2182
+ }
2183
+ if (options.bounds) {
2184
+ sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
2185
+ sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
2186
+ ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
2187
+ });
2188
+ }
2189
+ source = MGLRasterTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
2190
+ break;
2094
2191
  }
2192
+ default:
2193
+ reject('Invalid source type: ' + options['type']);
2194
+ return;
2095
2195
  }
2096
- else {
2196
+ if (!source) {
2197
+ const ex = 'No source to add';
2097
2198
  if (Trace.isEnabled()) {
2098
- CLog(CLogTypes.info, 'Please use res://resourceName, http(s)://imageUrl or iconPath to use a local path');
2199
+ CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
2099
2200
  }
2201
+ reject(ex);
2202
+ return;
2100
2203
  }
2204
+ theMap.style.addSource(source);
2205
+ resolve();
2101
2206
  }
2102
- else if (cachedMarker.iconPath) {
2103
- var appPath = knownFolders.currentApp().path;
2104
- var iconFullPath = appPath + '/' + cachedMarker.iconPath.replace('~/', '');
2105
- if (File.exists(iconFullPath)) {
2106
- var image = ImageSource.fromFileSync(iconFullPath).ios;
2107
- // perhaps add resize options for nice retina rendering (although you can now use the 'icon' param instead)
2108
- cachedMarker.reuseIdentifier = cachedMarker.iconPath;
2109
- return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(image, cachedMarker.reuseIdentifier);
2207
+ catch (ex) {
2208
+ if (Trace.isEnabled()) {
2209
+ CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
2110
2210
  }
2211
+ reject(ex);
2111
2212
  }
2112
- }
2113
- return null;
2114
- };
2115
- /**
2116
- * fired when one of the callout's accessoryviews is tapped (not currently used)
2117
- */
2118
- MGLMapViewDelegateImpl.prototype.mapViewAnnotationCalloutAccessoryControlTapped = function (mapView, annotation, control) { };
2119
- /**
2120
- * fired when a marker is tapped
2121
- */
2122
- MGLMapViewDelegateImpl.prototype.mapViewDidSelectAnnotation = function (mapView, annotation) {
2123
- if (Trace.isEnabled()) {
2124
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidSelectAnntation()');
2125
- }
2126
- if (annotation.isKindOfClass(MGLUserLocation.class())) {
2127
- if (Trace.isEnabled()) {
2128
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidSelectAnnotation(): tapped the user location button');
2213
+ });
2214
+ }
2215
+ removeSource(id, nativeMap) {
2216
+ return new Promise((resolve, reject) => {
2217
+ try {
2218
+ const theMap = nativeMap || this._mapboxViewInstance;
2219
+ if (!theMap) {
2220
+ reject('No map has been loaded');
2221
+ return;
2222
+ }
2223
+ const source = theMap.style.sourceWithIdentifier(id);
2224
+ if (!source) {
2225
+ reject('Source does not exist');
2226
+ return;
2227
+ }
2228
+ theMap.style.removeSource(source);
2229
+ resolve();
2129
2230
  }
2130
- if (typeof this.userLocationClickListener != 'undefined') {
2131
- this.userLocationClickListener(annotation);
2132
- return;
2231
+ catch (ex) {
2232
+ if (Trace.isEnabled()) {
2233
+ CLog(CLogTypes.info, 'Error in mapbox.removeSource: ' + ex);
2234
+ }
2235
+ reject(ex);
2133
2236
  }
2134
- mapView.deselectAnnotationAnimated(annotation, false);
2135
- }
2136
- var cachedMarker = this.getTappedMarkerDetails(annotation);
2137
- if (cachedMarker && cachedMarker.onTap) {
2138
- cachedMarker.onTap(cachedMarker);
2237
+ });
2238
+ }
2239
+ async addLayer(style, belowLayerId, nativeMapView) {
2240
+ const theMap = nativeMapView || this._mapboxViewInstance;
2241
+ let source = null;
2242
+ if (typeof style.source != 'string') {
2243
+ await this.addSource(style.id + '_source', style.source);
2244
+ source = theMap.style.sourceWithIdentifier(style.id + '_source');
2139
2245
  }
2140
- };
2141
- /**
2142
- * fired when a callout is tapped
2143
- */
2144
- MGLMapViewDelegateImpl.prototype.mapViewTapOnCalloutForAnnotation = function (mapView, annotation) {
2145
- var cachedMarker = this.getTappedMarkerDetails(annotation);
2146
- if (cachedMarker && cachedMarker.onCalloutTap) {
2147
- cachedMarker.onCalloutTap(cachedMarker);
2246
+ else {
2247
+ source = theMap.style.sourceWithIdentifier(style.source);
2148
2248
  }
2149
- };
2150
- MGLMapViewDelegateImpl.prototype.getTappedMarkerDetails = function (tapped) {
2151
- for (var m in _markers) {
2152
- var cached = _markers[m];
2153
- // don't compare lat/lng types as they're not the same (same for (sub)title, they may be null vs undefined)
2154
- if (
2155
- // eslint-disable-next-line eqeqeq
2156
- cached.lat == tapped.coordinate.latitude &&
2157
- // eslint-disable-next-line eqeqeq
2158
- cached.lng == tapped.coordinate.longitude &&
2159
- // eslint-disable-next-line eqeqeq
2160
- cached.title == tapped.title &&
2161
- // eslint-disable-next-line eqeqeq
2162
- cached.subtitle == tapped.subtitle) {
2163
- return cached;
2249
+ const layer = await LayerFactory.createLayer(style, source);
2250
+ if (belowLayerId) {
2251
+ const belowlayer = theMap.style.layerWithIdentifier(belowLayerId);
2252
+ if (belowlayer) {
2253
+ theMap.style.insertLayerBelowLayer(layer.getNativeInstance(), belowlayer);
2254
+ return;
2164
2255
  }
2165
2256
  }
2166
- };
2167
- /**
2168
- * override the standard location marker
2169
- */
2170
- MGLMapViewDelegateImpl.prototype.mapViewViewForAnnotation = function (mapView, annotation) {
2171
- if (Trace.isEnabled()) {
2172
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewViewForAnnotation() top');
2173
- }
2174
- if (annotation.isKindOfClass(MGLUserLocation.class())) {
2175
- this.userLocationAnnotationView = CustomUserLocationAnnotationView.alloc().init();
2176
- return this.userLocationAnnotationView;
2257
+ theMap.style.addLayer(layer.getNativeInstance());
2258
+ }
2259
+ async removeLayer(id, nativeMapViewInstance) {
2260
+ const theMap = nativeMapViewInstance || this._mapboxViewInstance;
2261
+ if (Trace.isEnabled()) {
2262
+ CLog(CLogTypes.info, "Mapbox::removeLayer(): attempting to remove layer '" + id + "'");
2177
2263
  }
2178
- return null;
2179
- };
2180
- MGLMapViewDelegateImpl.prototype.mapViewRegionIsChangingWithReason = function (mapView, reason) {
2264
+ const layer = theMap.style.layerWithIdentifier(id);
2181
2265
  if (Trace.isEnabled()) {
2182
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionIsChanging()');
2266
+ CLog(CLogTypes.info, 'Mapbox:removeLayer(): got layer object: ', layer);
2183
2267
  }
2184
- if (this.cameraChangedListener) {
2185
- this.cameraChangedListener(reason);
2268
+ if (!layer) {
2269
+ throw new Error("Layer '" + id + "' not found when attempting to remove it.");
2186
2270
  }
2187
- };
2188
- MGLMapViewDelegateImpl.prototype.mapViewRegionDidChangeWithReasonAnimated = function (mapView, reason, animated) {
2271
+ theMap.style.removeLayer(layer);
2189
2272
  if (Trace.isEnabled()) {
2190
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionDidChangeAnimated()');
2191
- }
2192
- if (this.cameraChangedListener) {
2193
- this.cameraChangedListener(reason, animated);
2273
+ CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer ' + id);
2194
2274
  }
2195
- if (this.cameraIdledListener) {
2196
- this.cameraIdledListener();
2275
+ }
2276
+ async addLinePoint(id, lnglat, sourceId, nativeMapView) {
2277
+ const theMap = nativeMapView || this._mapboxViewInstance;
2278
+ const sId = !!sourceId ? sourceId : id + '_source';
2279
+ const lineSource = theMap.style.sourceWithIdentifier(sId);
2280
+ if (!lineSource) {
2281
+ throw new Error(`no source found with id: ${sId}`);
2197
2282
  }
2198
- };
2199
- MGLMapViewDelegateImpl.prototype.mapViewDidUpdateUserLocation = function (mapView, userLocation) {
2200
- if (Trace.isEnabled()) {
2201
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidUpdateUserLocation()');
2283
+ try {
2284
+ const lineFeatures = lineSource.featuresMatchingPredicate(ExpressionParser.parseJson(['==', '$type', 'LineString']));
2285
+ if (lineFeatures.count === 0) {
2286
+ throw new Error('no line string feature found');
2287
+ }
2288
+ const lineFeature = lineFeatures.objectAtIndex(0);
2289
+ const newCoord = CLLocationCoordinate2DMake(lnglat[1], lnglat[0]);
2290
+ const newCoordPointer = new interop.Reference(newCoord);
2291
+ lineFeature.appendCoordinatesCount(newCoordPointer, 1);
2292
+ lineSource.shape = lineFeature;
2202
2293
  }
2203
- if (this.userLocationChangedListener) {
2204
- this.userLocationChangedListener(_getLocation(userLocation));
2294
+ catch (error) {
2295
+ console.log(error);
2296
+ throw error;
2205
2297
  }
2206
- };
2207
- MGLMapViewDelegateImpl.ObjCProtocols = [MGLMapViewDelegate];
2208
- return MGLMapViewDelegateImpl;
2209
- }(NSObject));
2210
- var MapTapHandlerImpl = /** @class */ (function (_super) {
2211
- __extends(MapTapHandlerImpl, _super);
2212
- function MapTapHandlerImpl() {
2213
- return _super !== null && _super.apply(this, arguments) || this;
2214
2298
  }
2215
- MapTapHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, mapView) {
2216
- var handler = MapTapHandlerImpl.new();
2217
- handler._owner = owner;
2218
- handler._listener = listener;
2219
- handler._mapView = mapView;
2220
- return handler;
2221
- };
2222
- MapTapHandlerImpl.prototype.tap = function (recognizer) {
2223
- var tapPoint = recognizer.locationInView(this._mapView);
2224
- var tapCoordinate = this._mapView.convertPointToCoordinateFromView(tapPoint, this._mapView);
2225
- this._listener({
2226
- lat: tapCoordinate.latitude,
2227
- lng: tapCoordinate.longitude
2228
- });
2229
- };
2230
- MapTapHandlerImpl.ObjCExposedMethods = {
2231
- tap: { returns: interop.types.void, params: [interop.types.id] }
2232
- };
2233
- return MapTapHandlerImpl;
2234
- }(NSObject));
2235
- var MapLongPressHandlerImpl = /** @class */ (function (_super) {
2236
- __extends(MapLongPressHandlerImpl, _super);
2237
- function MapLongPressHandlerImpl() {
2238
- return _super !== null && _super.apply(this, arguments) || this;
2299
+ addGeoJsonClustered(options, nativeMapViewInstance) {
2300
+ throw new Error('Method not implemented.');
2239
2301
  }
2240
- MapLongPressHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, mapView) {
2241
- var handler = MapLongPressHandlerImpl.new();
2242
- handler._owner = owner;
2243
- handler._listener = listener;
2244
- handler._mapView = mapView;
2245
- return handler;
2246
- };
2247
- MapLongPressHandlerImpl.prototype.longPress = function (recognizer) {
2248
- var longPressPoint = recognizer.locationInView(this._mapView);
2249
- var longPressCoordinate = this._mapView.convertPointToCoordinateFromView(longPressPoint, this._mapView);
2250
- this._listener({
2251
- lat: longPressCoordinate.latitude,
2252
- lng: longPressCoordinate.longitude
2302
+ trackUser(options, nativeMap) {
2303
+ return new Promise((resolve, reject) => {
2304
+ try {
2305
+ const theMap = nativeMap || this._mapboxViewInstance;
2306
+ if (!theMap) {
2307
+ reject('No map has been loaded');
2308
+ return;
2309
+ }
2310
+ if (!theMap.showsUserLocation) {
2311
+ reject('The map is not currently showing the user location');
2312
+ return;
2313
+ }
2314
+ theMap.setUserTrackingModeAnimated(_getTrackingMode(options.cameraMode), options.animated !== false);
2315
+ resolve();
2316
+ }
2317
+ catch (ex) {
2318
+ if (Trace.isEnabled()) {
2319
+ CLog(CLogTypes.info, 'Error in mapbox.trackUser: ' + ex);
2320
+ }
2321
+ reject(ex);
2322
+ }
2253
2323
  });
2254
- };
2255
- MapLongPressHandlerImpl.ObjCExposedMethods = {
2256
- longPress: { returns: interop.types.void, params: [interop.types.id] }
2257
- };
2258
- return MapLongPressHandlerImpl;
2259
- }(NSObject));
2260
- var MapPanHandlerImpl = /** @class */ (function (_super) {
2261
- __extends(MapPanHandlerImpl, _super);
2262
- function MapPanHandlerImpl() {
2263
- return _super !== null && _super.apply(this, arguments) || this;
2264
2324
  }
2265
- MapPanHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, mapView) {
2266
- var handler = MapPanHandlerImpl.new();
2267
- handler._owner = owner;
2268
- handler._listener = listener;
2269
- handler._mapView = mapView;
2270
- handler.onMoveBegin = false;
2271
- return handler;
2272
- };
2273
- MapPanHandlerImpl.prototype.setOnMoveBegin = function () {
2274
- this.onMoveBegin = true;
2275
- };
2276
- MapPanHandlerImpl.prototype.pan = function (recognizer) {
2277
- var panPoint = recognizer.locationInView(this._mapView);
2278
- var panCoordinate = this._mapView.convertPointToCoordinateFromView(panPoint, this._mapView);
2279
- if (Trace.isEnabled()) {
2280
- CLog(CLogTypes.info, 'MapPanHandlerImpl::pan(): top with state:', recognizer.state);
2281
- }
2282
- // if this is the beginning of the pan simulate the Android onMoveBegin
2283
- //
2284
- // See the objc platform declarations in objc!UIKit.d.ts. It doesn't quite match the apple documention
2285
- if (this.onMoveBegin) {
2286
- if (recognizer.state === UIGestureRecognizerState.Began) {
2325
+ getLayer(name, nativeMap) {
2326
+ return new Promise((resolve, reject) => {
2327
+ try {
2328
+ const theMap = nativeMap || this._mapboxViewInstance;
2329
+ if (!theMap) {
2330
+ reject('No map has been loaded');
2331
+ return;
2332
+ }
2333
+ const layer = theMap.style.layerWithIdentifier(name);
2334
+ resolve(new Layer(layer));
2335
+ }
2336
+ catch (ex) {
2287
2337
  if (Trace.isEnabled()) {
2288
- CLog(CLogTypes.info, 'MapPanHandlerImpl::pan(): calling onMoveBegin listener');
2338
+ CLog(CLogTypes.info, 'Error in mapbox.getLayer: ' + ex);
2289
2339
  }
2290
- this._listener({
2291
- lat: panCoordinate.latitude,
2292
- lng: panCoordinate.longitude
2293
- });
2340
+ reject(ex);
2294
2341
  }
2295
- return;
2296
- }
2297
- this._listener({
2298
- lat: panCoordinate.latitude,
2299
- lng: panCoordinate.longitude
2300
2342
  });
2301
- };
2302
- MapPanHandlerImpl.ObjCExposedMethods = {
2303
- pan: { returns: interop.types.void, params: [interop.types.id] }
2304
- };
2305
- return MapPanHandlerImpl;
2306
- }(NSObject));
2307
- var MapSwipeHandlerImpl = /** @class */ (function (_super) {
2308
- __extends(MapSwipeHandlerImpl, _super);
2309
- function MapSwipeHandlerImpl() {
2310
- return _super !== null && _super.apply(this, arguments) || this;
2311
2343
  }
2312
- MapSwipeHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, mapView) {
2313
- var handler = MapSwipeHandlerImpl.new();
2314
- handler._owner = owner;
2315
- handler._listener = listener;
2316
- handler._mapView = mapView;
2317
- return handler;
2318
- };
2319
- MapSwipeHandlerImpl.prototype.swipe = function (recognizer) {
2320
- var swipePoint = recognizer.locationInView(this._mapView);
2321
- var swipeCoordinate = this._mapView.convertPointToCoordinateFromView(swipePoint, this._mapView);
2322
- this._listener({
2323
- lat: swipeCoordinate.latitude,
2324
- lng: swipeCoordinate.longitude
2344
+ getLayers(nativeMap) {
2345
+ return new Promise((resolve, reject) => {
2346
+ try {
2347
+ const theMap = nativeMap || this._mapboxViewInstance;
2348
+ if (!theMap) {
2349
+ reject('No map has been loaded');
2350
+ return;
2351
+ }
2352
+ const layers = theMap.style.layers;
2353
+ const result = [];
2354
+ for (let i = 0; i < layers.count; i++) {
2355
+ result.push(new Layer(layers[i]));
2356
+ }
2357
+ resolve(result);
2358
+ }
2359
+ catch (ex) {
2360
+ if (Trace.isEnabled()) {
2361
+ CLog(CLogTypes.info, 'Error in mapbox.getLayers: ' + ex);
2362
+ }
2363
+ reject(ex);
2364
+ }
2325
2365
  });
2326
- };
2327
- MapSwipeHandlerImpl.ObjCExposedMethods = {
2328
- swipe: { returns: interop.types.void, params: [interop.types.id] }
2329
- };
2330
- return MapSwipeHandlerImpl;
2331
- }(NSObject));
2332
- export class Layer {
2333
- constructor(instance) {
2334
- this.instance = instance;
2335
- this.id = instance.identifier;
2336
- }
2337
- visibility() {
2338
- return this.instance.visible;
2339
- }
2340
- show() {
2341
- this.instance.visible = true;
2342
2366
  }
2343
- hide() {
2344
- this.instance.visible = false;
2345
- }
2346
- getNativeInstance() {
2347
- return this.instance;
2367
+ project(data) {
2368
+ const theMap = this._mapboxViewInstance;
2369
+ const { x, y } = theMap.convertCoordinateToPointToView({ latitude: data.lat, longitude: data.lng }, theMap);
2370
+ return { x, y };
2348
2371
  }
2349
- setFilter(filter) {
2350
- if (this.instance instanceof MGLVectorStyleLayer) {
2351
- this.instance.predicate = FilterParser.parseJson(filter);
2372
+ }
2373
+ const _addObserver = (eventName, callback) => NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(eventName, null, NSOperationQueue.mainQueue, callback);
2374
+ function _downloadImage(marker) {
2375
+ return new Promise((resolve, reject) => {
2376
+ if (Trace.isEnabled()) {
2377
+ CLog(CLogTypes.info, '>> _downloadImage');
2352
2378
  }
2353
- else {
2354
- throw new Error('Set filter only support for vector layer.');
2379
+ if (_markerIconDownloadCache[marker.icon]) {
2380
+ marker.iconDownloaded = _markerIconDownloadCache[marker.icon];
2381
+ if (Trace.isEnabled()) {
2382
+ CLog(CLogTypes.info, '>> marker.iconDownloaded: ' + marker.iconDownloaded);
2383
+ }
2384
+ resolve(marker);
2385
+ return;
2355
2386
  }
2356
- }
2357
- getFilter() {
2358
- return FilterParser.toJson(this.instance.predicate);
2359
- }
2387
+ Http.getImage(marker.icon).then((output) => {
2388
+ marker.iconDownloaded = output.ios;
2389
+ _markerIconDownloadCache[marker.icon] = marker.iconDownloaded;
2390
+ resolve(marker);
2391
+ }, (ignoredError) => {
2392
+ console.log(`Download failed for ${marker.icon} with error: ${ignoredError}`);
2393
+ resolve(marker);
2394
+ });
2395
+ });
2360
2396
  }
2361
- //# sourceMappingURL=mapbox.ios.js.map
2397
+ const _downloadMarkerImages = (markers) => {
2398
+ const iterations = [];
2399
+ const result = [];
2400
+ markers.forEach((marker) => {
2401
+ if (marker.icon && marker.icon.startsWith('http')) {
2402
+ const p = _downloadImage(marker).then((mark) => result.push(mark));
2403
+ iterations.push(p);
2404
+ }
2405
+ else {
2406
+ result.push(marker);
2407
+ }
2408
+ });
2409
+ return Promise.all(iterations).then(() => result);
2410
+ };
2411
+ //# sourceMappingURL=index.ios.js.map