@nativescript-community/ui-mapbox 6.2.7 → 6.2.11

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.
@@ -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 { FilterParser } from './filter/filter-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) => {
@@ -213,7 +619,29 @@ export class MapboxView extends MapboxViewBase {
213
619
  CLog(CLogTypes.info, 'initMap(): onMoveBegin listener');
214
620
  }
215
621
  this.notify({
216
- eventName: MapboxViewBase.moveBeginEvent,
622
+ eventName: MapboxViewBase.moveBeginEvent,
623
+ object: this,
624
+ map: this,
625
+ ios: this.nativeMapView
626
+ });
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,
217
645
  object: this,
218
646
  map: this,
219
647
  ios: this.nativeMapView
@@ -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);
@@ -804,424 +1228,62 @@ export class Mapbox extends MapboxCommon {
804
1228
  try {
805
1229
  const theMap = nativeMap || this._mapboxViewInstance;
806
1230
  const coordinate = theMap.centerCoordinate;
807
- resolve({
808
- lat: coordinate.latitude,
809
- lng: coordinate.longitude
810
- });
811
- }
812
- catch (ex) {
813
- if (Trace.isEnabled()) {
814
- CLog(CLogTypes.info, 'Error in mapbox.getCenter: ' + ex);
815
- }
816
- reject(ex);
817
- }
818
- });
819
- }
820
- setZoomLevel(options, nativeMap) {
821
- return new Promise((resolve, reject) => {
822
- try {
823
- const theMap = nativeMap || this._mapboxViewInstance;
824
- const animated = options.animated === undefined || options.animated;
825
- const level = options.level;
826
- if (level >= 0 && level <= 20) {
827
- 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);
1055
- }
1056
- 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)));
1064
- }
1065
- resolve(result);
1231
+ resolve({
1232
+ lat: coordinate.latitude,
1233
+ lng: coordinate.longitude
1234
+ });
1066
1235
  }
1067
1236
  catch (ex) {
1068
1237
  if (Trace.isEnabled()) {
1069
- CLog(CLogTypes.info, 'Error in mapbox.querySourceFeatures: ' + ex);
1238
+ CLog(CLogTypes.info, 'Error in mapbox.getCenter: ' + ex);
1070
1239
  }
1071
1240
  reject(ex);
1072
1241
  }
1073
1242
  });
1074
1243
  }
1075
- addPolygon(options, nativeMap) {
1244
+ setZoomLevel(options, nativeMap) {
1076
1245
  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;
1246
+ try {
1247
+ const theMap = nativeMap || this._mapboxViewInstance;
1248
+ const animated = options.animated === undefined || options.animated;
1249
+ const level = options.level;
1250
+ if (level >= 0 && level <= 20) {
1251
+ theMap.setZoomLevelAnimated(level, animated);
1252
+ resolve();
1253
+ }
1254
+ else {
1255
+ reject('invalid ZoomLevel, use any double value from 0 to 20 (like 8.3)');
1256
+ }
1089
1257
  }
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
- }
1258
+ catch (ex) {
1259
+ if (Trace.isEnabled()) {
1260
+ CLog(CLogTypes.info, 'Error in mapbox.setZoomLevel: ' + ex);
1102
1261
  }
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);
1262
+ reject(ex);
1118
1263
  }
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
1264
  });
1125
1265
  }
1126
- addPolyline(options, nativeMap) {
1266
+ getZoomLevel(nativeMap) {
1127
1267
  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;
1268
+ try {
1269
+ const theMap = nativeMap || this._mapboxViewInstance;
1270
+ resolve(theMap.zoomLevel);
1133
1271
  }
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;
1272
+ catch (ex) {
1273
+ if (Trace.isEnabled()) {
1274
+ CLog(CLogTypes.info, 'Error in mapbox.getZoomLevel: ' + ex);
1275
+ }
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
- });
1156
- }
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
1278
  });
1177
1279
  }
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,341 +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 = Mapbox.merge(options.padding === undefined ? {} : options.padding, {
1411
- top: 25,
1412
- left: 25,
1413
- bottom: 25,
1414
- right: 25
1415
- });
1416
- theMap.setVisibleCoordinateBoundsEdgePaddingAnimated(bounds, padding, animated);
1417
- 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 ? FilterParser.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);
1418
1448
  }
1419
1449
  catch (ex) {
1420
1450
  if (Trace.isEnabled()) {
1421
- CLog(CLogTypes.info, 'Error in mapbox.setViewport: ' + ex);
1451
+ CLog(CLogTypes.info, 'Error in mapbox.queryRenderedFeatures: ' + ex);
1422
1452
  }
1423
1453
  reject(ex);
1424
1454
  }
1425
1455
  });
1426
1456
  }
1427
- downloadOfflineRegion(options) {
1457
+ querySourceFeatures(sourceId, options, nativeMap) {
1428
1458
  return new Promise((resolve, reject) => {
1429
1459
  try {
1430
- const styleURL = _getMapStyle(options.style);
1431
- const swCoordinate = CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west);
1432
- const neCoordinate = CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east);
1433
- const bounds = {
1434
- sw: swCoordinate,
1435
- ne: neCoordinate
1436
- };
1437
- const region = MGLTilePyramidOfflineRegion.alloc().initWithStyleURLBoundsFromZoomLevelToZoomLevel(styleURL, bounds, options.minZoom, options.maxZoom);
1438
- if (options.accessToken) {
1439
- MGLAccountManager.accessToken = options.accessToken;
1460
+ const theMap = nativeMap || this._mapboxViewInstance;
1461
+ if (!options) {
1462
+ options = {};
1440
1463
  }
1441
- if (options.onProgress) {
1442
- _addObserver(MGLOfflinePackProgressChangedNotification, (notification) => {
1443
- const offlinePack = notification.object;
1444
- const offlinePackProgress = offlinePack.progress;
1445
- const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1446
- const complete = offlinePackProgress.countOfResourcesCompleted === offlinePackProgress.countOfResourcesExpected;
1447
- options.onProgress({
1448
- name: userInfo.objectForKey('name'),
1449
- completed: offlinePackProgress.countOfResourcesCompleted,
1450
- expected: offlinePackProgress.countOfResourcesExpected,
1451
- percentage: Math.round((offlinePackProgress.countOfResourcesCompleted / offlinePackProgress.countOfResourcesExpected) * 10000) / 100,
1452
- complete
1453
- });
1454
- if (complete) {
1455
- resolve();
1456
- }
1457
- });
1464
+ const source = theMap.style.sourceWithIdentifier(sourceId);
1465
+ if (!source) {
1466
+ throw new Error(`Source with id "${sourceId}" not found.`);
1458
1467
  }
1459
- _addObserver(MGLOfflinePackErrorNotification, (notification) => {
1460
- const offlinePack = notification.object;
1461
- const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1462
- const error = notification.userInfo[MGLOfflinePackUserInfoKeyError];
1463
- reject({
1464
- name: userInfo.objectForKey('name'),
1465
- error: 'Download error. ' + error
1466
- });
1467
- });
1468
- _addObserver(MGLOfflinePackMaximumMapboxTilesReachedNotification, (notification) => {
1469
- const offlinePack = notification.object;
1470
- const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1471
- const maximumCount = notification.userInfo[MGLOfflinePackUserInfoKeyMaximumCount];
1472
- console.log(`Offline region '${userInfo.objectForKey('name')}' reached the tile limit of ${maximumCount}`);
1473
- });
1474
- const userInfo = { name: options.name };
1475
- const context = NSKeyedArchiver.archivedDataWithRootObject(userInfo);
1476
- MGLOfflineStorage.sharedOfflineStorage.addPackForRegionWithContextCompletionHandler(region, context, (pack, error) => {
1477
- if (error) {
1478
- reject(error.localizedFailureReason);
1479
- }
1480
- else {
1481
- pack.resume();
1468
+ let features;
1469
+ const queryFilter = options.filter ? FilterParser.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.');
1482
1476
  }
1483
- });
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);
1484
1490
  }
1485
1491
  catch (ex) {
1486
1492
  if (Trace.isEnabled()) {
1487
- CLog(CLogTypes.info, 'Error in mapbox.downloadOfflineRegion: ' + ex);
1493
+ CLog(CLogTypes.info, 'Error in mapbox.querySourceFeatures: ' + ex);
1488
1494
  }
1489
1495
  reject(ex);
1490
1496
  }
1491
1497
  });
1492
1498
  }
1493
- listOfflineRegions(options) {
1499
+ addPolygon(options, nativeMap) {
1494
1500
  return new Promise((resolve, reject) => {
1495
- try {
1496
- const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
1497
- if (!packs) {
1498
- reject('No packs found or Mapbox not ready yet');
1499
- return;
1500
- }
1501
- const regions = [];
1502
- for (let i = 0; i < packs.count; i++) {
1503
- const pack = packs.objectAtIndex(i);
1504
- const region = pack.region;
1505
- const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
1506
- regions.push({
1507
- name: userInfo.objectForKey('name'),
1508
- style: '' + region.styleURL,
1509
- minZoom: region.minimumZoomLevel,
1510
- maxZoom: region.maximumZoomLevel,
1511
- bounds: {
1512
- north: region.bounds.ne.latitude,
1513
- east: region.bounds.ne.longitude,
1514
- south: region.bounds.sw.latitude,
1515
- west: region.bounds.sw.longitude
1516
- }
1517
- });
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
+ }
1518
1526
  }
1519
- 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;
1520
1557
  }
1521
- catch (ex) {
1522
- if (Trace.isEnabled()) {
1523
- CLog(CLogTypes.info, 'Error in mapbox.listOfflineRegions: ' + ex);
1524
- }
1525
- 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;
1526
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();
1527
1579
  });
1528
1580
  }
1529
- 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) {
1530
1609
  return new Promise((resolve, reject) => {
1531
1610
  try {
1532
- if (!options || !options.name) {
1533
- reject("Pass in the 'name' param");
1534
- 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);
1535
1626
  }
1536
- const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
1537
- let found = false;
1538
- for (let i = 0; i < packs.count; i++) {
1539
- const pack = packs.objectAtIndex(i);
1540
- const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
1541
- const name = userInfo.objectForKey('name');
1542
- if (name === options.name) {
1543
- found = true;
1544
- MGLOfflineStorage.sharedOfflineStorage.removePackWithCompletionHandler(pack, (error) => {
1545
- if (error) {
1546
- reject(error.localizedFailureReason);
1547
- }
1548
- else {
1549
- resolve();
1550
- }
1551
- });
1627
+ else {
1628
+ const target = options.target;
1629
+ if (target === undefined) {
1630
+ reject("Please set the 'target' parameter");
1631
+ return;
1552
1632
  }
1633
+ cam = theMap.camera;
1634
+ cam.centerCoordinate = CLLocationCoordinate2DMake(target.lat, target.lng);
1553
1635
  }
1554
- if (!found) {
1555
- 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;
1644
+ }
1645
+ if (options.zoomLevel && options.target) {
1646
+ cam.altitude = MGLAltitudeForZoomLevel(options.zoomLevel, cam.pitch, options.target.lat, theMap.frame.size);
1556
1647
  }
1648
+ const durationMs = options.duration ? options.duration : 10000;
1649
+ theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
1650
+ setTimeout(() => {
1651
+ resolve();
1652
+ }, durationMs);
1557
1653
  }
1558
1654
  catch (ex) {
1559
1655
  if (Trace.isEnabled()) {
1560
- CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
1656
+ CLog(CLogTypes.info, 'Error in mapbox.animateCamera: ' + ex);
1561
1657
  }
1562
1658
  reject(ex);
1563
1659
  }
1564
1660
  });
1565
1661
  }
1566
- addExtrusion(options, nativeMap) {
1662
+ setOnMapClickListener(listener, nativeMap) {
1567
1663
  return new Promise((resolve, reject) => {
1568
1664
  try {
1569
1665
  const theMap = nativeMap || this._mapboxViewInstance;
@@ -1571,17 +1667,20 @@ export class Mapbox extends MapboxCommon {
1571
1667
  reject('No map has been loaded');
1572
1668
  return;
1573
1669
  }
1670
+ theMap['mapTapHandler'] = MapTapHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
1671
+ const tapGestureRecognizer = UITapGestureRecognizer.alloc().initWithTargetAction(theMap['mapTapHandler'], 'tap');
1672
+ theMap.addGestureRecognizer(tapGestureRecognizer);
1574
1673
  resolve();
1575
1674
  }
1576
1675
  catch (ex) {
1577
1676
  if (Trace.isEnabled()) {
1578
- CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
1677
+ CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
1579
1678
  }
1580
1679
  reject(ex);
1581
1680
  }
1582
1681
  });
1583
1682
  }
1584
- updateSource(id, options, nativeMap) {
1683
+ setOnMapLongClickListener(listener, nativeMap) {
1585
1684
  return new Promise((resolve, reject) => {
1586
1685
  try {
1587
1686
  const theMap = nativeMap || this._mapboxViewInstance;
@@ -1589,154 +1688,88 @@ export class Mapbox extends MapboxCommon {
1589
1688
  reject('No map has been loaded');
1590
1689
  return;
1591
1690
  }
1592
- const source = theMap.style.sourceWithIdentifier(id);
1593
- if (!source) {
1594
- reject('Source does not exists: ' + id);
1595
- return;
1596
- }
1597
- switch (options.type) {
1598
- case 'geojson':
1599
- const content = NSString.stringWithString(JSON.stringify(options.data));
1600
- const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
1601
- const geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
1602
- source.shape = geoJsonShape;
1603
- break;
1604
- default:
1605
- reject('Invalid source type: ' + options['type']);
1606
- return;
1691
+ theMap['mapLongPressHandler'] = MapLongPressHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
1692
+ const longPressGestureRecognizer = UILongPressGestureRecognizer.alloc().initWithTargetAction(theMap['mapLongPressHandler'], 'longPress');
1693
+ for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1694
+ const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1695
+ if (recognizer instanceof UILongPressGestureRecognizer) {
1696
+ longPressGestureRecognizer.requireGestureRecognizerToFail(recognizer);
1697
+ }
1607
1698
  }
1699
+ theMap.addGestureRecognizer(longPressGestureRecognizer);
1700
+ resolve();
1608
1701
  }
1609
1702
  catch (ex) {
1610
1703
  if (Trace.isEnabled()) {
1611
- CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
1612
- }
1613
- reject(ex);
1614
- }
1615
- });
1616
- }
1617
- addSource(id, options, nativeMap) {
1618
- return new Promise((resolve, reject) => {
1619
- try {
1620
- const theMap = nativeMap || this._mapboxViewInstance;
1621
- let source;
1622
- if (!theMap) {
1623
- reject('No map has been loaded');
1624
- return;
1625
- }
1626
- if (theMap.style.sourceWithIdentifier(id)) {
1627
- reject('Source exists: ' + id);
1628
- return;
1629
- }
1630
- switch (options.type) {
1631
- case 'vector': {
1632
- if (options.url) {
1633
- source = MGLVectorTileSource.alloc().initWithIdentifierConfigurationURL(id, NSURL.URLWithString(options.url));
1634
- }
1635
- else {
1636
- const sourceOptions = {};
1637
- if (options.minzoom !== undefined) {
1638
- sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
1639
- }
1640
- if (options.maxzoom !== undefined) {
1641
- sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
1642
- }
1643
- if (options.scheme) {
1644
- switch (options.scheme) {
1645
- case 'xyz':
1646
- sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
1647
- break;
1648
- case 'tms':
1649
- sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
1650
- break;
1651
- default:
1652
- throw new Error('Unknown raster tile scheme.');
1653
- }
1654
- }
1655
- if (options.bounds) {
1656
- sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
1657
- sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
1658
- ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
1659
- });
1660
- }
1661
- source = MGLVectorTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
1662
- }
1663
- break;
1664
- }
1665
- case 'geojson':
1666
- if (theMap.style.sourceWithIdentifier(id)) {
1667
- reject("Remove the layer with this id first with 'removeLayer': " + id);
1668
- return;
1669
- }
1670
- let geoJsonShape;
1671
- if (options.data) {
1672
- const content = NSString.stringWithString(JSON.stringify(options.data));
1673
- const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
1674
- geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
1675
- }
1676
- const sourceOptions = {};
1677
- if (options.minzoom !== undefined) {
1678
- sourceOptions[MGLShapeSourceOptionMinimumZoomLevel] = options.minzoom;
1679
- }
1680
- if (options.maxzoom !== undefined) {
1681
- sourceOptions[MGLShapeSourceOptionMaximumZoomLevel] = options.maxzoom;
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);
1704
+ CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
1705
+ }
1706
+ reject(ex);
1707
+ }
1708
+ });
1709
+ }
1710
+ setOnScrollListener(listener, nativeMap) {
1711
+ return new Promise((resolve, reject) => {
1712
+ try {
1713
+ const theMap = nativeMap || this._mapboxViewInstance;
1714
+ if (!theMap) {
1715
+ reject('No map has been loaded');
1716
+ return;
1717
+ }
1718
+ if (theMap['mapPanHandler'] === undefined) {
1719
+ theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 2, theMap);
1720
+ }
1721
+ else {
1722
+ theMap['mapPanHandler'].addListener(2, listener);
1723
+ }
1724
+ for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1725
+ const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1726
+ if (recognizer instanceof UIPanGestureRecognizer) {
1727
+ recognizer.addTargetAction(theMap['mapPanHandler'], 'pan');
1714
1728
  break;
1715
1729
  }
1716
- default:
1717
- reject('Invalid source type: ' + options['type']);
1718
- return;
1719
1730
  }
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);
1731
+ resolve();
1732
+ }
1733
+ catch (ex) {
1734
+ if (Trace.isEnabled()) {
1735
+ CLog(CLogTypes.info, 'Error in mapbox.setOnScrollListener: ' + ex);
1736
+ }
1737
+ reject(ex);
1738
+ }
1739
+ });
1740
+ }
1741
+ setOnMoveBeginListener(listener, nativeMap) {
1742
+ return new Promise((resolve, reject) => {
1743
+ try {
1744
+ const theMap = nativeMap || this._mapboxViewInstance;
1745
+ if (!theMap) {
1746
+ reject('No map has been loaded');
1726
1747
  return;
1727
1748
  }
1728
- theMap.style.addSource(source);
1749
+ if (theMap['mapPanHandler'] === undefined) {
1750
+ theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 1, theMap);
1751
+ }
1752
+ else {
1753
+ theMap['mapPanHandler'].addListener(1, listener);
1754
+ }
1755
+ for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1756
+ const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1757
+ if (recognizer instanceof UIPanGestureRecognizer) {
1758
+ recognizer.addTargetAction(theMap['mapPanHandler'], 'panBegin');
1759
+ break;
1760
+ }
1761
+ }
1729
1762
  resolve();
1730
1763
  }
1731
1764
  catch (ex) {
1732
1765
  if (Trace.isEnabled()) {
1733
- CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
1766
+ CLog(CLogTypes.info, 'Error in mapbox.setOnMoveBeginListener: ' + ex);
1734
1767
  }
1735
1768
  reject(ex);
1736
1769
  }
1737
1770
  });
1738
1771
  }
1739
- removeSource(id, nativeMap) {
1772
+ setOnMoveEndListener(listener, nativeMap) {
1740
1773
  return new Promise((resolve, reject) => {
1741
1774
  try {
1742
1775
  const theMap = nativeMap || this._mapboxViewInstance;
@@ -1744,86 +1777,82 @@ export class Mapbox extends MapboxCommon {
1744
1777
  reject('No map has been loaded');
1745
1778
  return;
1746
1779
  }
1747
- const source = theMap.style.sourceWithIdentifier(id);
1748
- if (!source) {
1749
- reject('Source does not exist');
1750
- return;
1780
+ if (theMap['mapPanHandler'] === undefined) {
1781
+ theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 3, theMap);
1782
+ }
1783
+ else {
1784
+ theMap['mapPanHandler'].addListener(3, listener);
1785
+ }
1786
+ for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
1787
+ const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
1788
+ if (recognizer instanceof UIPanGestureRecognizer) {
1789
+ recognizer.addTargetAction(theMap['mapPanHandler'], 'panEnd');
1790
+ break;
1791
+ }
1751
1792
  }
1752
- theMap.style.removeSource(source);
1753
1793
  resolve();
1754
1794
  }
1755
1795
  catch (ex) {
1756
1796
  if (Trace.isEnabled()) {
1757
- CLog(CLogTypes.info, 'Error in mapbox.removeSource: ' + ex);
1797
+ CLog(CLogTypes.info, 'Error in mapbox.setOnMoveEndListener: ' + ex);
1758
1798
  }
1759
1799
  reject(ex);
1760
1800
  }
1761
1801
  });
1762
1802
  }
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');
1803
+ setOnFlingListener(listener, nativeMap) {
1804
+ return Promise.reject("'setOnFlingListener' is not supported on iOS");
1805
+ }
1806
+ async setOnCameraMoveListener(listener, nativeMap) {
1807
+ const theMap = nativeMap || this._mapboxViewInstance;
1808
+ if (theMap) {
1809
+ theMap.delegate.setCameraChangedListener(listener);
1769
1810
  }
1770
1811
  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
- }
1812
+ return Promise.reject('No map has been loaded');
1780
1813
  }
1781
- theMap.style.addLayer(layer.getNativeInstance());
1782
1814
  }
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.");
1794
- }
1795
- theMap.style.removeLayer(layer);
1796
- if (Trace.isEnabled()) {
1797
- CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer ' + id);
1798
- }
1815
+ setOnCameraMoveCancelListener(listener, nativeMap) {
1816
+ return Promise.reject("'setOnCameraMoveCancelListener' not currently supported on iOS");
1799
1817
  }
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');
1811
- }
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;
1818
+ async setOnCameraIdleListener(listener, nativeMap) {
1819
+ const theMap = nativeMap || this._mapboxViewInstance;
1820
+ if (theMap) {
1821
+ theMap.delegate.setCameraIdledListener(listener);
1817
1822
  }
1818
- catch (error) {
1819
- console.log(error);
1820
- throw error;
1823
+ else {
1824
+ return Promise.reject('No map has been loaded');
1821
1825
  }
1822
1826
  }
1823
- addGeoJsonClustered(options, nativeMapViewInstance) {
1824
- throw new Error('Method not implemented.');
1827
+ getViewport(nativeMap) {
1828
+ return new Promise((resolve, reject) => {
1829
+ try {
1830
+ const theMap = nativeMap || this._mapboxViewInstance;
1831
+ if (!theMap) {
1832
+ reject('No map has been loaded');
1833
+ return;
1834
+ }
1835
+ const visibleBounds = theMap.visibleCoordinateBounds;
1836
+ const bounds = {
1837
+ north: visibleBounds.ne.latitude,
1838
+ east: visibleBounds.ne.longitude,
1839
+ south: visibleBounds.sw.latitude,
1840
+ west: visibleBounds.sw.longitude
1841
+ };
1842
+ resolve({
1843
+ bounds,
1844
+ zoomLevel: theMap.zoomLevel
1845
+ });
1846
+ }
1847
+ catch (ex) {
1848
+ if (Trace.isEnabled()) {
1849
+ CLog(CLogTypes.info, 'Error in mapbox.getViewport: ' + ex);
1850
+ }
1851
+ reject(ex);
1852
+ }
1853
+ });
1825
1854
  }
1826
- trackUser(options, nativeMap) {
1855
+ setViewport(options, nativeMap) {
1827
1856
  return new Promise((resolve, reject) => {
1828
1857
  try {
1829
1858
  const theMap = nativeMap || this._mapboxViewInstance;
@@ -1831,41 +1860,163 @@ export class Mapbox extends MapboxCommon {
1831
1860
  reject('No map has been loaded');
1832
1861
  return;
1833
1862
  }
1834
- if (!theMap.showsUserLocation) {
1835
- reject('The map is not currently showing the user location');
1836
- return;
1863
+ const bounds = {
1864
+ sw: CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west),
1865
+ ne: CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east)
1866
+ };
1867
+ const animated = options.animated === undefined || options.animated;
1868
+ 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 };
1869
+ theMap.setVisibleCoordinateBoundsEdgePaddingAnimated(bounds, padding, animated);
1870
+ resolve();
1871
+ }
1872
+ catch (ex) {
1873
+ if (Trace.isEnabled()) {
1874
+ CLog(CLogTypes.info, 'Error in mapbox.setViewport: ' + ex);
1875
+ }
1876
+ reject(ex);
1877
+ }
1878
+ });
1879
+ }
1880
+ downloadOfflineRegion(options) {
1881
+ return new Promise((resolve, reject) => {
1882
+ try {
1883
+ const styleURL = _getMapStyle(options.style);
1884
+ const swCoordinate = CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west);
1885
+ const neCoordinate = CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east);
1886
+ const bounds = {
1887
+ sw: swCoordinate,
1888
+ ne: neCoordinate
1889
+ };
1890
+ const region = MGLTilePyramidOfflineRegion.alloc().initWithStyleURLBoundsFromZoomLevelToZoomLevel(styleURL, bounds, options.minZoom, options.maxZoom);
1891
+ if (options.accessToken) {
1892
+ MGLAccountManager.accessToken = options.accessToken;
1893
+ }
1894
+ if (options.onProgress) {
1895
+ _addObserver(MGLOfflinePackProgressChangedNotification, (notification) => {
1896
+ const offlinePack = notification.object;
1897
+ const offlinePackProgress = offlinePack.progress;
1898
+ const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1899
+ const complete = offlinePackProgress.countOfResourcesCompleted === offlinePackProgress.countOfResourcesExpected;
1900
+ options.onProgress({
1901
+ name: userInfo.objectForKey('name'),
1902
+ completed: offlinePackProgress.countOfResourcesCompleted,
1903
+ expected: offlinePackProgress.countOfResourcesExpected,
1904
+ percentage: Math.round((offlinePackProgress.countOfResourcesCompleted / offlinePackProgress.countOfResourcesExpected) * 10000) / 100,
1905
+ complete
1906
+ });
1907
+ if (complete) {
1908
+ resolve();
1909
+ }
1910
+ });
1911
+ }
1912
+ _addObserver(MGLOfflinePackErrorNotification, (notification) => {
1913
+ const offlinePack = notification.object;
1914
+ const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1915
+ const error = notification.userInfo[MGLOfflinePackUserInfoKeyError];
1916
+ reject({
1917
+ name: userInfo.objectForKey('name'),
1918
+ error: 'Download error. ' + error
1919
+ });
1920
+ });
1921
+ _addObserver(MGLOfflinePackMaximumMapboxTilesReachedNotification, (notification) => {
1922
+ const offlinePack = notification.object;
1923
+ const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
1924
+ const maximumCount = notification.userInfo[MGLOfflinePackUserInfoKeyMaximumCount];
1925
+ console.log(`Offline region '${userInfo.objectForKey('name')}' reached the tile limit of ${maximumCount}`);
1926
+ });
1927
+ const userInfo = { name: options.name };
1928
+ const context = NSKeyedArchiver.archivedDataWithRootObject(userInfo);
1929
+ MGLOfflineStorage.sharedOfflineStorage.addPackForRegionWithContextCompletionHandler(region, context, (pack, error) => {
1930
+ if (error) {
1931
+ reject(error.localizedFailureReason);
1932
+ }
1933
+ else {
1934
+ pack.resume();
1935
+ }
1936
+ });
1937
+ }
1938
+ catch (ex) {
1939
+ if (Trace.isEnabled()) {
1940
+ CLog(CLogTypes.info, 'Error in mapbox.downloadOfflineRegion: ' + ex);
1941
+ }
1942
+ reject(ex);
1943
+ }
1944
+ });
1945
+ }
1946
+ listOfflineRegions(options) {
1947
+ return new Promise((resolve, reject) => {
1948
+ try {
1949
+ const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
1950
+ if (!packs) {
1951
+ reject('No packs found or Mapbox not ready yet');
1952
+ return;
1953
+ }
1954
+ const regions = [];
1955
+ for (let i = 0; i < packs.count; i++) {
1956
+ const pack = packs.objectAtIndex(i);
1957
+ const region = pack.region;
1958
+ const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
1959
+ regions.push({
1960
+ name: userInfo.objectForKey('name'),
1961
+ style: '' + region.styleURL,
1962
+ minZoom: region.minimumZoomLevel,
1963
+ maxZoom: region.maximumZoomLevel,
1964
+ bounds: {
1965
+ north: region.bounds.ne.latitude,
1966
+ east: region.bounds.ne.longitude,
1967
+ south: region.bounds.sw.latitude,
1968
+ west: region.bounds.sw.longitude
1969
+ }
1970
+ });
1837
1971
  }
1838
- theMap.setUserTrackingModeAnimated(_getTrackingMode(options.mode), options.animated !== false);
1839
- resolve();
1972
+ resolve(regions);
1840
1973
  }
1841
1974
  catch (ex) {
1842
1975
  if (Trace.isEnabled()) {
1843
- CLog(CLogTypes.info, 'Error in mapbox.trackUser: ' + ex);
1976
+ CLog(CLogTypes.info, 'Error in mapbox.listOfflineRegions: ' + ex);
1844
1977
  }
1845
1978
  reject(ex);
1846
1979
  }
1847
1980
  });
1848
1981
  }
1849
- getLayer(name, nativeMap) {
1982
+ deleteOfflineRegion(options) {
1850
1983
  return new Promise((resolve, reject) => {
1851
1984
  try {
1852
- const theMap = nativeMap || this._mapboxViewInstance;
1853
- if (!theMap) {
1854
- reject('No map has been loaded');
1985
+ if (!options || (!options.id && !options.name)) {
1986
+ reject("Pass in the 'id' or 'name' param");
1855
1987
  return;
1856
1988
  }
1857
- const layer = theMap.style.layerWithIdentifier(name);
1858
- resolve(new Layer(layer));
1989
+ const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
1990
+ let found = false;
1991
+ for (let i = 0; i < packs.count; i++) {
1992
+ const pack = packs.objectAtIndex(i);
1993
+ const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
1994
+ const regionId = options.id ? userInfo.objectForKey('id') : userInfo.objectForKey('name');
1995
+ if (regionId === (options.id || options.name)) {
1996
+ found = true;
1997
+ MGLOfflineStorage.sharedOfflineStorage.removePackWithCompletionHandler(pack, (error) => {
1998
+ if (error) {
1999
+ reject(error.localizedFailureReason);
2000
+ }
2001
+ else {
2002
+ resolve();
2003
+ }
2004
+ });
2005
+ }
2006
+ }
2007
+ if (!found) {
2008
+ reject('Region not found');
2009
+ }
1859
2010
  }
1860
2011
  catch (ex) {
1861
2012
  if (Trace.isEnabled()) {
1862
- CLog(CLogTypes.info, 'Error in mapbox.getLayer: ' + ex);
2013
+ CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
1863
2014
  }
1864
2015
  reject(ex);
1865
2016
  }
1866
2017
  });
1867
2018
  }
1868
- getLayers(nativeMap) {
2019
+ addExtrusion(options, nativeMap) {
1869
2020
  return new Promise((resolve, reject) => {
1870
2021
  try {
1871
2022
  const theMap = nativeMap || this._mapboxViewInstance;
@@ -1873,489 +2024,370 @@ export class Mapbox extends MapboxCommon {
1873
2024
  reject('No map has been loaded');
1874
2025
  return;
1875
2026
  }
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);
2027
+ resolve();
1882
2028
  }
1883
2029
  catch (ex) {
1884
2030
  if (Trace.isEnabled()) {
1885
- CLog(CLogTypes.info, 'Error in mapbox.getLayers: ' + ex);
2031
+ CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
1886
2032
  }
1887
2033
  reject(ex);
1888
2034
  }
1889
2035
  });
1890
2036
  }
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;
2037
+ updateSource(id, options, nativeMap) {
2038
+ return new Promise((resolve, reject) => {
2039
+ try {
2040
+ const theMap = nativeMap || this._mapboxViewInstance;
2041
+ if (!theMap) {
2042
+ reject('No map has been loaded');
2043
+ return;
2044
+ }
2045
+ const source = theMap.style.sourceWithIdentifier(id);
2046
+ if (!source) {
2047
+ reject('Source does not exists: ' + id);
2048
+ return;
2049
+ }
2050
+ switch (options.type) {
2051
+ case 'geojson':
2052
+ const content = NSString.stringWithString(JSON.stringify(options.data));
2053
+ const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
2054
+ const geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
2055
+ source.shape = geoJsonShape;
2056
+ break;
2057
+ default:
2058
+ reject('Invalid source type: ' + options['type']);
2059
+ return;
2074
2060
  }
2075
2061
  }
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
- }
2062
+ catch (ex) {
2063
+ if (Trace.isEnabled()) {
2064
+ CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
2089
2065
  }
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);
2066
+ reject(ex);
2067
+ }
2068
+ });
2069
+ }
2070
+ addSource(id, options, nativeMap) {
2071
+ return new Promise((resolve, reject) => {
2072
+ try {
2073
+ const theMap = nativeMap || this._mapboxViewInstance;
2074
+ let source;
2075
+ if (!theMap) {
2076
+ reject('No map has been loaded');
2077
+ return;
2078
+ }
2079
+ if (theMap.style.sourceWithIdentifier(id)) {
2080
+ reject('Source exists: ' + id);
2081
+ return;
2082
+ }
2083
+ switch (options.type) {
2084
+ case 'vector': {
2085
+ if (options.url) {
2086
+ source = MGLVectorTileSource.alloc().initWithIdentifierConfigurationURL(id, NSURL.URLWithString(options.url));
2087
+ }
2088
+ else {
2089
+ const sourceOptions = {};
2090
+ if (options.minzoom !== undefined) {
2091
+ sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
2092
+ }
2093
+ if (options.maxzoom !== undefined) {
2094
+ sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
2095
+ }
2096
+ if (options.scheme) {
2097
+ switch (options.scheme) {
2098
+ case 'xyz':
2099
+ sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
2100
+ break;
2101
+ case 'tms':
2102
+ sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
2103
+ break;
2104
+ default:
2105
+ throw new Error('Unknown raster tile scheme.');
2106
+ }
2107
+ }
2108
+ if (options.bounds) {
2109
+ sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
2110
+ sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
2111
+ ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
2112
+ });
2113
+ }
2114
+ source = MGLVectorTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
2115
+ }
2116
+ break;
2117
+ }
2118
+ case 'geojson':
2119
+ if (theMap.style.sourceWithIdentifier(id)) {
2120
+ reject("Remove the layer with this id first with 'removeLayer': " + id);
2121
+ return;
2122
+ }
2123
+ let geoJsonShape;
2124
+ if (options.data) {
2125
+ const content = NSString.stringWithString(JSON.stringify(options.data));
2126
+ const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
2127
+ geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
2128
+ }
2129
+ const sourceOptions = {};
2130
+ if (options.minzoom !== undefined) {
2131
+ sourceOptions[MGLShapeSourceOptionMinimumZoomLevel] = options.minzoom;
2132
+ }
2133
+ if (options.maxzoom !== undefined) {
2134
+ sourceOptions[MGLShapeSourceOptionMaximumZoomLevel] = options.maxzoom;
2135
+ }
2136
+ if (options.cluster) {
2137
+ sourceOptions[MGLShapeSourceOptionClustered] = true;
2138
+ sourceOptions[MGLShapeSourceOptionClusterRadius] = options.cluster.radius || 40;
2139
+ sourceOptions[MGLShapeSourceOptionMaximumZoomLevelForClustering] = options.cluster.maxZoom || 13;
2140
+ }
2141
+ source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, geoJsonShape, sourceOptions);
2142
+ break;
2143
+ case 'raster': {
2144
+ const sourceOptions = {
2145
+ [MGLTileSourceOptionTileSize]: options.tileSize || 256
2146
+ };
2147
+ if (options.minzoom !== undefined) {
2148
+ sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
2149
+ }
2150
+ if (options.maxzoom !== undefined) {
2151
+ sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
2152
+ }
2153
+ if (options.scheme) {
2154
+ switch (options.scheme || 'xyz') {
2155
+ case 'xyz':
2156
+ sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
2157
+ break;
2158
+ case 'tms':
2159
+ sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
2160
+ break;
2161
+ default:
2162
+ throw new Error('Unknown raster tile scheme.');
2163
+ }
2164
+ }
2165
+ if (options.bounds) {
2166
+ sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
2167
+ sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
2168
+ ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
2169
+ });
2170
+ }
2171
+ source = MGLRasterTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
2172
+ break;
2094
2173
  }
2174
+ default:
2175
+ reject('Invalid source type: ' + options['type']);
2176
+ return;
2095
2177
  }
2096
- else {
2178
+ if (!source) {
2179
+ const ex = 'No source to add';
2097
2180
  if (Trace.isEnabled()) {
2098
- CLog(CLogTypes.info, 'Please use res://resourceName, http(s)://imageUrl or iconPath to use a local path');
2181
+ CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
2099
2182
  }
2183
+ reject(ex);
2184
+ return;
2100
2185
  }
2186
+ theMap.style.addSource(source);
2187
+ resolve();
2101
2188
  }
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);
2189
+ catch (ex) {
2190
+ if (Trace.isEnabled()) {
2191
+ CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
2110
2192
  }
2193
+ reject(ex);
2111
2194
  }
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');
2195
+ });
2196
+ }
2197
+ removeSource(id, nativeMap) {
2198
+ return new Promise((resolve, reject) => {
2199
+ try {
2200
+ const theMap = nativeMap || this._mapboxViewInstance;
2201
+ if (!theMap) {
2202
+ reject('No map has been loaded');
2203
+ return;
2204
+ }
2205
+ const source = theMap.style.sourceWithIdentifier(id);
2206
+ if (!source) {
2207
+ reject('Source does not exist');
2208
+ return;
2209
+ }
2210
+ theMap.style.removeSource(source);
2211
+ resolve();
2129
2212
  }
2130
- if (typeof this.userLocationClickListener != 'undefined') {
2131
- this.userLocationClickListener(annotation);
2132
- return;
2213
+ catch (ex) {
2214
+ if (Trace.isEnabled()) {
2215
+ CLog(CLogTypes.info, 'Error in mapbox.removeSource: ' + ex);
2216
+ }
2217
+ reject(ex);
2133
2218
  }
2134
- mapView.deselectAnnotationAnimated(annotation, false);
2135
- }
2136
- var cachedMarker = this.getTappedMarkerDetails(annotation);
2137
- if (cachedMarker && cachedMarker.onTap) {
2138
- cachedMarker.onTap(cachedMarker);
2219
+ });
2220
+ }
2221
+ async addLayer(style, belowLayerId, nativeMapView) {
2222
+ const theMap = nativeMapView || this._mapboxViewInstance;
2223
+ let source = null;
2224
+ if (typeof style.source != 'string') {
2225
+ await this.addSource(style.id + '_source', style.source);
2226
+ source = theMap.style.sourceWithIdentifier(style.id + '_source');
2139
2227
  }
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);
2228
+ else {
2229
+ source = theMap.style.sourceWithIdentifier(style.source);
2148
2230
  }
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;
2231
+ const layer = await LayerFactory.createLayer(style, source);
2232
+ if (belowLayerId) {
2233
+ const belowlayer = theMap.style.layerWithIdentifier(belowLayerId);
2234
+ if (belowlayer) {
2235
+ theMap.style.insertLayerBelowLayer(layer.getNativeInstance(), belowlayer);
2236
+ return;
2164
2237
  }
2165
2238
  }
2166
- };
2167
- /**
2168
- * override the standard location marker
2169
- */
2170
- MGLMapViewDelegateImpl.prototype.mapViewViewForAnnotation = function (mapView, annotation) {
2239
+ theMap.style.addLayer(layer.getNativeInstance());
2240
+ }
2241
+ async removeLayer(id, nativeMapViewInstance) {
2242
+ const theMap = nativeMapViewInstance || this._mapboxViewInstance;
2171
2243
  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;
2244
+ CLog(CLogTypes.info, "Mapbox::removeLayer(): attempting to remove layer '" + id + "'");
2177
2245
  }
2178
- return null;
2179
- };
2180
- MGLMapViewDelegateImpl.prototype.mapViewRegionIsChangingWithReason = function (mapView, reason) {
2246
+ const layer = theMap.style.layerWithIdentifier(id);
2181
2247
  if (Trace.isEnabled()) {
2182
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionIsChanging()');
2248
+ CLog(CLogTypes.info, 'Mapbox:removeLayer(): got layer object: ', layer);
2183
2249
  }
2184
- if (this.cameraChangedListener) {
2185
- this.cameraChangedListener(reason);
2250
+ if (!layer) {
2251
+ throw new Error("Layer '" + id + "' not found when attempting to remove it.");
2186
2252
  }
2187
- };
2188
- MGLMapViewDelegateImpl.prototype.mapViewRegionDidChangeWithReasonAnimated = function (mapView, reason, animated) {
2253
+ theMap.style.removeLayer(layer);
2189
2254
  if (Trace.isEnabled()) {
2190
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionDidChangeAnimated()');
2191
- }
2192
- if (this.cameraChangedListener) {
2193
- this.cameraChangedListener(reason, animated);
2255
+ CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer ' + id);
2194
2256
  }
2195
- if (this.cameraIdledListener) {
2196
- this.cameraIdledListener();
2257
+ }
2258
+ async addLinePoint(id, lnglat, sourceId, nativeMapView) {
2259
+ const theMap = nativeMapView || this._mapboxViewInstance;
2260
+ const sId = !!sourceId ? sourceId : id + '_source';
2261
+ const lineSource = theMap.style.sourceWithIdentifier(sId);
2262
+ if (!lineSource) {
2263
+ throw new Error(`no source found with id: ${sId}`);
2197
2264
  }
2198
- };
2199
- MGLMapViewDelegateImpl.prototype.mapViewDidUpdateUserLocation = function (mapView, userLocation) {
2200
- if (Trace.isEnabled()) {
2201
- CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidUpdateUserLocation()');
2265
+ try {
2266
+ const lineFeatures = lineSource.featuresMatchingPredicate(FilterParser.parseJson(['==', '$type', 'LineString']));
2267
+ if (lineFeatures.count === 0) {
2268
+ throw new Error('no line string feature found');
2269
+ }
2270
+ const lineFeature = lineFeatures.objectAtIndex(0);
2271
+ const newCoord = CLLocationCoordinate2DMake(lnglat[1], lnglat[0]);
2272
+ const newCoordPointer = new interop.Reference(newCoord);
2273
+ lineFeature.appendCoordinatesCount(newCoordPointer, 1);
2274
+ lineSource.shape = lineFeature;
2202
2275
  }
2203
- if (this.userLocationChangedListener) {
2204
- this.userLocationChangedListener(_getLocation(userLocation));
2276
+ catch (error) {
2277
+ console.log(error);
2278
+ throw error;
2205
2279
  }
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
2280
  }
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;
2281
+ addGeoJsonClustered(options, nativeMapViewInstance) {
2282
+ throw new Error('Method not implemented.');
2239
2283
  }
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
2284
+ trackUser(options, nativeMap) {
2285
+ return new Promise((resolve, reject) => {
2286
+ try {
2287
+ const theMap = nativeMap || this._mapboxViewInstance;
2288
+ if (!theMap) {
2289
+ reject('No map has been loaded');
2290
+ return;
2291
+ }
2292
+ if (!theMap.showsUserLocation) {
2293
+ reject('The map is not currently showing the user location');
2294
+ return;
2295
+ }
2296
+ theMap.setUserTrackingModeAnimated(_getTrackingMode(options.cameraMode), options.animated !== false);
2297
+ resolve();
2298
+ }
2299
+ catch (ex) {
2300
+ if (Trace.isEnabled()) {
2301
+ CLog(CLogTypes.info, 'Error in mapbox.trackUser: ' + ex);
2302
+ }
2303
+ reject(ex);
2304
+ }
2253
2305
  });
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
2306
  }
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) {
2307
+ getLayer(name, nativeMap) {
2308
+ return new Promise((resolve, reject) => {
2309
+ try {
2310
+ const theMap = nativeMap || this._mapboxViewInstance;
2311
+ if (!theMap) {
2312
+ reject('No map has been loaded');
2313
+ return;
2314
+ }
2315
+ const layer = theMap.style.layerWithIdentifier(name);
2316
+ resolve(new Layer(layer));
2317
+ }
2318
+ catch (ex) {
2287
2319
  if (Trace.isEnabled()) {
2288
- CLog(CLogTypes.info, 'MapPanHandlerImpl::pan(): calling onMoveBegin listener');
2320
+ CLog(CLogTypes.info, 'Error in mapbox.getLayer: ' + ex);
2289
2321
  }
2290
- this._listener({
2291
- lat: panCoordinate.latitude,
2292
- lng: panCoordinate.longitude
2293
- });
2322
+ reject(ex);
2294
2323
  }
2295
- return;
2296
- }
2297
- this._listener({
2298
- lat: panCoordinate.latitude,
2299
- lng: panCoordinate.longitude
2300
2324
  });
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
2325
  }
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
2326
+ getLayers(nativeMap) {
2327
+ return new Promise((resolve, reject) => {
2328
+ try {
2329
+ const theMap = nativeMap || this._mapboxViewInstance;
2330
+ if (!theMap) {
2331
+ reject('No map has been loaded');
2332
+ return;
2333
+ }
2334
+ const layers = theMap.style.layers;
2335
+ const result = [];
2336
+ for (let i = 0; i < layers.count; i++) {
2337
+ result.push(new Layer(layers[i]));
2338
+ }
2339
+ resolve(result);
2340
+ }
2341
+ catch (ex) {
2342
+ if (Trace.isEnabled()) {
2343
+ CLog(CLogTypes.info, 'Error in mapbox.getLayers: ' + ex);
2344
+ }
2345
+ reject(ex);
2346
+ }
2325
2347
  });
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
2348
  }
2343
- hide() {
2344
- this.instance.visible = false;
2345
- }
2346
- getNativeInstance() {
2347
- return this.instance;
2349
+ project(data) {
2350
+ const theMap = this._mapboxViewInstance;
2351
+ const { x, y } = theMap.convertCoordinateToPointToView({ latitude: data.lat, longitude: data.lng }, theMap);
2352
+ return { x, y };
2348
2353
  }
2349
- setFilter(filter) {
2350
- if (this.instance instanceof MGLVectorStyleLayer) {
2351
- this.instance.predicate = FilterParser.parseJson(filter);
2354
+ }
2355
+ const _addObserver = (eventName, callback) => NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(eventName, null, NSOperationQueue.mainQueue, callback);
2356
+ function _downloadImage(marker) {
2357
+ return new Promise((resolve, reject) => {
2358
+ if (Trace.isEnabled()) {
2359
+ CLog(CLogTypes.info, '>> _downloadImage');
2352
2360
  }
2353
- else {
2354
- throw new Error('Set filter only support for vector layer.');
2361
+ if (_markerIconDownloadCache[marker.icon]) {
2362
+ marker.iconDownloaded = _markerIconDownloadCache[marker.icon];
2363
+ if (Trace.isEnabled()) {
2364
+ CLog(CLogTypes.info, '>> marker.iconDownloaded: ' + marker.iconDownloaded);
2365
+ }
2366
+ resolve(marker);
2367
+ return;
2355
2368
  }
2356
- }
2357
- getFilter() {
2358
- return FilterParser.toJson(this.instance.predicate);
2359
- }
2369
+ Http.getImage(marker.icon).then((output) => {
2370
+ marker.iconDownloaded = output.ios;
2371
+ _markerIconDownloadCache[marker.icon] = marker.iconDownloaded;
2372
+ resolve(marker);
2373
+ }, (ignoredError) => {
2374
+ console.log(`Download failed for ${marker.icon} with error: ${ignoredError}`);
2375
+ resolve(marker);
2376
+ });
2377
+ });
2360
2378
  }
2361
- //# sourceMappingURL=mapbox.ios.js.map
2379
+ const _downloadMarkerImages = (markers) => {
2380
+ const iterations = [];
2381
+ const result = [];
2382
+ markers.forEach((marker) => {
2383
+ if (marker.icon && marker.icon.startsWith('http')) {
2384
+ const p = _downloadImage(marker).then((mark) => result.push(mark));
2385
+ iterations.push(p);
2386
+ }
2387
+ else {
2388
+ result.push(marker);
2389
+ }
2390
+ });
2391
+ return Promise.all(iterations).then(() => result);
2392
+ };
2393
+ //# sourceMappingURL=index.ios.js.map