@nativescript-community/ui-mapbox 6.2.15 → 6.2.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.android.js CHANGED
@@ -1,8 +1,14 @@
1
+ /**
2
+ * Android Implementation
3
+ *
4
+ * @todo FIXME: The gcFix() implementation currently assumes only one map visible at a time.
5
+ */
1
6
  import { request } from '@nativescript-community/perms';
2
- import { AndroidApplication, Application, Color, File, Http, ImageSource, Trace, Utils, knownFolders, path } from '@nativescript/core';
7
+ import { AndroidApplication, Application, Color, File, Http, Image, ImageSource, Trace, Utils, knownFolders, path } from '@nativescript/core';
3
8
  import { ExpressionParser } from './expression/expression-parser';
4
9
  import { Layer, LayerFactory } from './layers/layer-factory';
5
- import { CLog, CLogTypes, MapStyle, MapboxCommon, MapboxViewBase, telemetryProperty } from './common';
10
+ import { CLog, CLogTypes, MapStyle, MapboxCommon, MapboxTraceCategory, MapboxViewBase, telemetryProperty } from './common';
11
+ // Export the enums for devs not using TS
6
12
  export * from './common';
7
13
  function _getLocation(loc) {
8
14
  if (loc === null) {
@@ -41,17 +47,39 @@ export function setLogLevel(level) {
41
47
  }
42
48
  Logger.setVerbosity(loggingLevel);
43
49
  }
50
+ /**
51
+ * A map view created in XML.
52
+ *
53
+ * This is the class that is created when the Mapbox XML tag
54
+ * is encountered while parsing a view.
55
+ *
56
+ * Angular components need to register the Mapbox tag as follows:
57
+ *
58
+ * import { registerElement } from "nativescript-angular/element-registry";
59
+ * registerElement( "Mapbox", () => require("nativescript-mapbox").MapboxView);
60
+ *
61
+ * The registerElement call is what binds the XML tag to the class that creates it.
62
+ *
63
+ * @see MapboxViewBase
64
+ */
44
65
  export class MapboxView extends MapboxViewBase {
45
66
  constructor() {
46
67
  super();
47
68
  this.settings = null;
69
+ // whether or not the view has already been initialized.
70
+ // see initNativeView()
48
71
  this.initialized = false;
49
72
  if (Trace.isEnabled()) {
50
73
  CLog(CLogTypes.info, 'constructor(): building new MapboxView object.');
51
74
  }
52
75
  }
76
+ /**
77
+ * programmatically include settings
78
+ */
53
79
  setConfig(settings) {
80
+ // zoom level is not applied unless center is set
54
81
  if (settings.zoomLevel && !settings.center) {
82
+ // Eiffel tower, Paris
55
83
  settings.center = {
56
84
  lat: 48.858093,
57
85
  lng: 2.294694
@@ -62,9 +90,36 @@ export class MapboxView extends MapboxViewBase {
62
90
  getNativeMapView() {
63
91
  return this.nativeMapView;
64
92
  }
93
+ /**
94
+ * Return the Mapbox() API Shim instance
95
+ *
96
+ * This returns a reference to the Mapbox API shim class instance.
97
+ * See class Mapbox below.
98
+ *
99
+ * @see Mapbox
100
+ */
65
101
  getMapboxApi() {
66
102
  return this.mapbox;
67
103
  }
104
+ /**
105
+ * Creates the native view.
106
+ *
107
+ * This method is supposed to create the native view. NativeScript caches
108
+ * and re-uses views to save on memory and increase performance. Unfortunately,
109
+ * the inner details of exactly how this is done is challenging to tease apart.
110
+ *
111
+ * The problem is that in order to create the Mapbox view we need the access token from
112
+ * the XML, but in the case of a pure NativeScript app with property binding
113
+ * (see the demo), the properties don't seem to be available until the page is loaded.
114
+ *
115
+ * As a workaround, I wait until the page is loaded to configure the map. See initNativeView.
116
+ *
117
+ * It seems to me there should be a better way.
118
+ *
119
+ * @link https://docs.nativescript.org/core-concepts/properties#views-lifecycle-and-recycling
120
+ *
121
+ * @todo check this.
122
+ */
68
123
  createNativeView() {
69
124
  if (Trace.isEnabled()) {
70
125
  CLog(CLogTypes.info, 'createNativeView(): top');
@@ -90,28 +145,56 @@ export class MapboxView extends MapboxViewBase {
90
145
  CLog(CLogTypes.info, 'initNativeView(): top');
91
146
  }
92
147
  this.nativeView.owner = this;
148
+ // Application.android.on(AndroidApplication.activityStartedEvent, this.onStart, this);
93
149
  Application.android.on(AndroidApplication.activityPausedEvent, this.onPause, this);
94
150
  Application.android.on(AndroidApplication.activityResumedEvent, this.onResume, this);
151
+ // Application.android.on(AndroidApplication.activityStartedEvent, this.onStop, this);
95
152
  super.initNativeView();
96
153
  }
154
+ /**
155
+ * when the view is destroyed.
156
+ *
157
+ * This is called by the framework when the view is actually destroyed.
158
+ * NativeScript, by design, tries to cache native views because
159
+ * creating native views is expensive.
160
+ *
161
+ * @link https://docs.nativescript.org/plugins/ui-plugin-custom
162
+ */
97
163
  disposeNativeView() {
98
164
  if (Trace.isEnabled()) {
99
165
  CLog(CLogTypes.info, 'disposeNativeView(): top');
100
166
  }
101
167
  this.nativeView.owner = null;
168
+ // Application.android.off(AndroidApplication.activityStartedEvent, this.onStart, this);
102
169
  Application.android.off(AndroidApplication.activityPausedEvent, this.onPause, this);
103
170
  Application.android.off(AndroidApplication.activityResumedEvent, this.onResume, this);
171
+ // Application.android.off(AndroidApplication.activityStartedEvent, this.onStop, this);
104
172
  if (this.mapbox) {
105
173
  this.mapbox.destroy();
106
174
  }
107
175
  super.disposeNativeView();
108
176
  }
177
+ /**
178
+ * initialize the map
179
+ *
180
+ * This method creates a new mapbox API instance and, through the show() method of the Mapbox API,
181
+ * creates a Mapbox native map view.
182
+ *
183
+ * @see show()
184
+ *
185
+ * @link https://docs.nativescript.org/core-concepts/events
186
+ *
187
+ * @todo FIXME: this.nativeMapView is unused and never actually set to anything.
188
+ */
109
189
  initMap() {
110
190
  if (Trace.isEnabled()) {
111
191
  CLog(CLogTypes.info, "MapboxView:initMap(): top - accessToken is '" + this.config.accessToken + "'", this.config);
112
192
  }
113
193
  if (!this.nativeMapView && ((this.config && this.config.accessToken) || (this.settings && this.settings.accessToken))) {
114
194
  this.mapbox = new Mapbox(this);
195
+ // the NativeScript contentview class extends from Observable to provide the notify method
196
+ // which is the glue that joins this code with whatever callbacks are set in the Mapbox XML
197
+ // tag describing the map.
115
198
  const options = {
116
199
  context: this._context,
117
200
  parentView: this.nativeView,
@@ -223,6 +306,16 @@ export class MapboxView extends MapboxViewBase {
223
306
  }
224
307
  }
225
308
  }
309
+ /**
310
+ * A NativeScript shim for the Mapbox API.
311
+ *
312
+ * This implements a Typescript shim over the Native Mapbox GL Android API.
313
+ *
314
+ * It is created in one of two ways:
315
+ *
316
+ * - directly via let mapbox = new Mapbox(); mapbox.show( ... )
317
+ * - via the Mapbox XML tag in which case a MapboxView object is created which hosts a reference to this class. (See MapboxView::getMapboxAPI())
318
+ */
226
319
  export class Mapbox extends MapboxCommon {
227
320
  constructor(view) {
228
321
  super(view);
@@ -233,7 +326,9 @@ export class Mapbox extends MapboxCommon {
233
326
  this._markers = [];
234
327
  this._polylines = [];
235
328
  this._polygons = [];
329
+ // list of polylines
236
330
  this.lines = [];
331
+ // registered callbacks.
237
332
  this.eventCallbacks = {};
238
333
  this._markerIconDownloadCache = [];
239
334
  this.iconCache = {};
@@ -245,7 +340,29 @@ export class Mapbox extends MapboxCommon {
245
340
  CLog(CLogTypes.info, 'constructor(): end of Mapbox constructor.');
246
341
  }
247
342
  }
343
+ /**
344
+ * not used
345
+ */
248
346
  setMapboxViewInstance(mapboxViewInstance) { }
347
+ /**
348
+ * show the map programmatically.
349
+ *
350
+ * This method is used to programmatically display a map. It is also called
351
+ * by the MapboxView::init() method which initializes the map when the Mapbox
352
+ * XML tags is encountered
353
+ *
354
+ * options may additionally include:
355
+ *
356
+ * - context
357
+ * - parentView
358
+ * - onLocationPermissionGranted
359
+ * - onLocationPermissionDenied
360
+ * - onMapReady
361
+ *
362
+ * @see MapboxView::init()
363
+ *
364
+ * @todo FIXME: the timeout delay before showing the map works around some race condition. The source error needs to be figured out.
365
+ */
249
366
  show(options) {
250
367
  return new Promise((resolve, reject) => {
251
368
  try {
@@ -254,10 +371,14 @@ export class Mapbox extends MapboxCommon {
254
371
  if (Trace.isEnabled()) {
255
372
  CLog(CLogTypes.info, 'show()');
256
373
  }
374
+ // if no accessToken was set the app may crash.
375
+ //
376
+ // FIXME: Even if using a local server add some string.
257
377
  if (settings.accessToken === undefined) {
258
378
  reject('mapbox_accesstoken_missing');
259
379
  return;
260
380
  }
381
+ // if already added, make sure it's removed first
261
382
  if (this._mapboxViewInstance) {
262
383
  if (Trace.isEnabled()) {
263
384
  CLog(CLogTypes.info, 'show(): view already created. Removing it.');
@@ -275,10 +396,20 @@ export class Mapbox extends MapboxCommon {
275
396
  if (settings.context) {
276
397
  context = settings.context;
277
398
  }
399
+ // Per the Mapbox Android Native samples:
400
+ //
401
+ // "Mapbox access token is configured here. This needs to be called either in your application
402
+ // object or in the same activity which contains the mapview."
278
403
  com.mapbox.mapboxsdk.Mapbox.getInstance(context, this._accessToken);
279
404
  const mapboxMapOptions = this._getMapboxMapOptions(settings);
405
+ // unlike the Mapbox Android Native samples, we are not laying the map out
406
+ // using the Android XML layout features. Instead, we are creating the map
407
+ // programmatically.
280
408
  this._mapboxViewInstance = new com.mapbox.mapboxsdk.maps.MapView(context, mapboxMapOptions);
409
+ // required per the Mapbox Android API.
281
410
  this._mapboxViewInstance.onCreate(null);
411
+ // define some listeners to inform in case the map does not
412
+ // load.
282
413
  if (Trace.isEnabled()) {
283
414
  this.onDidFailLoadingMapListener = new com.mapbox.mapboxsdk.maps.MapView.OnDidFailLoadingMapListener({
284
415
  onDidFailLoadingMap: (error) => CLog(CLogTypes.error, 'Mapbox::show(): failed to load map:', error)
@@ -297,16 +428,21 @@ export class Mapbox extends MapboxCommon {
297
428
  if (Trace.isEnabled()) {
298
429
  CLog(CLogTypes.info, 'show(): onMapReady() with instance:', this._mapboxMapInstance);
299
430
  }
431
+ // Android SDK 7.0.0 and on requires that the style be set separately after the map
432
+ // is initialized. We do not consider the map ready until the style has successfully
433
+ // loaded.
300
434
  this.setMapStyle(settings.style).then((style) => {
301
435
  if (Trace.isEnabled()) {
302
436
  CLog(CLogTypes.info, 'show(): style loaded.');
303
437
  }
438
+ // initialize the event handlers now that we have a constructed view.
304
439
  this.initEventHandlerShim(settings, this._mapboxViewInstance);
305
440
  this._addMarkers(settings.markers, this._mapboxViewInstance);
306
441
  if (settings.showUserLocation) {
307
442
  this.requestFineLocationPermission()
308
443
  .then(() => {
309
444
  this.showUserLocationMarker(settings.locationComponentOptions);
445
+ // if we have a callback defined, call it.
310
446
  if (settings.onLocationPermissionGranted) {
311
447
  settings.onLocationPermissionGranted(this._mapboxMapInstance);
312
448
  }
@@ -317,6 +453,7 @@ export class Mapbox extends MapboxCommon {
317
453
  }
318
454
  });
319
455
  }
456
+ // if we have an onMapReady callback fire it.
320
457
  if (settings.onMapReady) {
321
458
  settings.onMapReady(this._mapboxMapInstance);
322
459
  }
@@ -330,6 +467,8 @@ export class Mapbox extends MapboxCommon {
330
467
  if (Trace.isEnabled()) {
331
468
  CLog(CLogTypes.info, 'show(): after getMapAsync()');
332
469
  }
470
+ // we either have been given a view to add the map to or we
471
+ // add it to the top making it full screen.
333
472
  if (settings.parentView) {
334
473
  if (Trace.isEnabled()) {
335
474
  CLog(CLogTypes.info, 'show(): adding map to passed in view');
@@ -340,6 +479,7 @@ export class Mapbox extends MapboxCommon {
340
479
  if (Trace.isEnabled()) {
341
480
  CLog(CLogTypes.info, 'show(): adding map to passed in container');
342
481
  }
482
+ // Application.android.currentContext has been removed.
343
483
  context = Application.android.foregroundActivity;
344
484
  if (!context) {
345
485
  context = Application.android.startActivity;
@@ -358,6 +498,7 @@ export class Mapbox extends MapboxCommon {
358
498
  CLog(CLogTypes.info, 'show(): showIt() bottom');
359
499
  }
360
500
  };
501
+ // FIXME: There is some initialization error. A short delay works around this.
361
502
  setTimeout(showIt, settings.delay ? settings.delay : 200);
362
503
  }
363
504
  catch (ex) {
@@ -368,6 +509,9 @@ export class Mapbox extends MapboxCommon {
368
509
  }
369
510
  });
370
511
  }
512
+ /**
513
+ * hide the map
514
+ */
371
515
  hide() {
372
516
  return new Promise((resolve, reject) => {
373
517
  try {
@@ -406,6 +550,11 @@ export class Mapbox extends MapboxCommon {
406
550
  }
407
551
  });
408
552
  }
553
+ /**
554
+ * destroy the map programmatically
555
+ *
556
+ * Destroy the map instance.
557
+ */
409
558
  destroy(nativeMap) {
410
559
  return new Promise(async (resolve, reject) => {
411
560
  this.clearEventListeners();
@@ -425,6 +574,10 @@ export class Mapbox extends MapboxCommon {
425
574
  this.symbolManager.onDestroy();
426
575
  this.symbolManager = null;
427
576
  }
577
+ // if we have a location marker we need to disable it before destroying the map
578
+ //
579
+ // This is here to prevent a crash. The user code should disable/re-enable the
580
+ // location marker.
428
581
  if (this._locationComponent) {
429
582
  if (Trace.isEnabled()) {
430
583
  CLog(CLogTypes.info, 'destroy(): Location marker not disabled before destroy() called.');
@@ -442,6 +595,7 @@ export class Mapbox extends MapboxCommon {
442
595
  this._mapboxViewInstance.onPause();
443
596
  this._mapboxViewInstance.onStop();
444
597
  this._mapboxViewInstance.destroyDrawingCache();
598
+ // let the API know that we're programmatically destroying the map.
445
599
  this._mapboxViewInstance.onDestroy();
446
600
  this._mapboxViewInstance = null;
447
601
  this._mapboxMapInstance = null;
@@ -449,6 +603,14 @@ export class Mapbox extends MapboxCommon {
449
603
  resolve();
450
604
  });
451
605
  }
606
+ /**
607
+ * Clear Event Listeners
608
+ *
609
+ * Explicitly clear all registered event listeners. It's not clear to me whether or not this
610
+ * is strictly necessary as I imagine these should all get cleaned up when the map is destroyed
611
+ * but given the complication of NativeScript's garbage collection scheme it seems like a good
612
+ * idea to remove these handlers explicitly.
613
+ */
452
614
  clearEventListeners() {
453
615
  if (this.onDidFailLoadingMapListener) {
454
616
  this._mapboxViewInstance.removeOnDidFailLoadingMapListener(this.onDidFailLoadingMapListener);
@@ -515,6 +677,9 @@ export class Mapbox extends MapboxCommon {
515
677
  this.onLocationClickListener = null;
516
678
  }
517
679
  }
680
+ // ------------------------------------------------
681
+ // Life Cycle Hooks
682
+ // ------------------------------------------------
518
683
  async onStart(nativeMap) {
519
684
  if (Trace.isEnabled()) {
520
685
  CLog(CLogTypes.info, 'onStart()');
@@ -551,6 +716,14 @@ export class Mapbox extends MapboxCommon {
551
716
  }
552
717
  this._mapboxViewInstance.onDestroy();
553
718
  }
719
+ /**
720
+ * event handler shim
721
+ *
722
+ * Initialize our event handler shim so that we can intercept events here.
723
+ *
724
+ * @param { any } settings
725
+ * @param { MapboxView } mapboxView
726
+ */
554
727
  initEventHandlerShim(settings, mapboxNativeViewInstance) {
555
728
  if (Trace.isEnabled()) {
556
729
  CLog(CLogTypes.info, 'Mapbox:initEventHandlerShim(): top');
@@ -581,6 +754,22 @@ export class Mapbox extends MapboxCommon {
581
754
  }
582
755
  }, mapboxNativeViewInstance);
583
756
  }
757
+ /**
758
+ * register on click handlers.
759
+ *
760
+ * The native mapbox API does not, apparently, support click handlers
761
+ * on circles, but it does for markers and polylines. WTF?
762
+ *
763
+ * Here we attempt to replicate the mapbox-gl-js behaviour of being
764
+ * able to assign an onClick handler to a layer by it's layer id.
765
+ *
766
+ * @param {string} event - the event to subscribe to. i.e. 'click'.
767
+ * @param {string} id - the id of the layer
768
+ * @param {function} callback - the callback to invoke when the layer is clicked on.
769
+ * @param {object] nativeMapView - reference to the native Map view.
770
+ *
771
+ * @link https://github.com/mapbox/mapbox-android-demo/issues/540
772
+ */
584
773
  onMapEvent(eventName, id, callback, nativeMapView) {
585
774
  if (typeof this.eventCallbacks[eventName] == 'undefined') {
586
775
  this.eventCallbacks[eventName] = [];
@@ -590,12 +779,21 @@ export class Mapbox extends MapboxCommon {
590
779
  callback
591
780
  });
592
781
  }
782
+ /**
783
+ * remove an event handler for a layer
784
+ *
785
+ * This will remove all event handlers (that we manage here) for
786
+ * the given layer id and event.
787
+ */
593
788
  offMapEvent(eventName, id, nativeMapView) {
594
789
  if (typeof this.eventCallbacks[eventName] == 'undefined') {
595
790
  return;
596
791
  }
597
792
  this.eventCallbacks[eventName] = this.eventCallbacks[eventName].filter((entry) => entry.id !== id);
598
793
  }
794
+ /**
795
+ * If click events registered and a feature found for the event, then fire listener.
796
+ */
599
797
  checkForClickEvent(point, nativeMap) {
600
798
  if (Trace.isEnabled()) {
601
799
  CLog(CLogTypes.info, 'Mapbox:checkForClickEvent(): got click event with point:', JSON.stringify(point));
@@ -611,6 +809,12 @@ export class Mapbox extends MapboxCommon {
611
809
  this.view && this.view.notify({ eventName: 'mapClick', object: this.view, point });
612
810
  return false;
613
811
  }
812
+ /**
813
+ * handles a line click event
814
+ *
815
+ * Given a click on a line overlay, find the id of the underlying line layer
816
+ * an invoke any registered callbacks.
817
+ */
614
818
  handleLineClickEvent(clickOverlay) {
615
819
  const lineEntry = this.lines.find((entry) => {
616
820
  if (Trace.isEnabled()) {
@@ -633,7 +837,7 @@ export class Mapbox extends MapboxCommon {
633
837
  }
634
838
  return entry.callback(lineEntry);
635
839
  }
636
- }
840
+ } // end of for loop over events.
637
841
  return false;
638
842
  }
639
843
  hasFineLocationPermission() {
@@ -649,9 +853,30 @@ export class Mapbox extends MapboxCommon {
649
853
  }
650
854
  });
651
855
  }
856
+ /**
857
+ * Request fine locaion permission
858
+ *
859
+ * @link https://docs.mapbox.com/android/core/overview/#permissionsmanager
860
+ */
652
861
  async requestFineLocationPermission() {
653
862
  return request('location');
654
863
  }
864
+ /**
865
+ * set the map style
866
+ *
867
+ * The 7.X version of the SDK uses a builder class for forming
868
+ * URLs.
869
+ *
870
+ * NOTE: The style must be explicitly set using this method in the onMapReady() handler.
871
+ *
872
+ * @param {string | MapStyle } style - a style following the Mapbox style specification or a URL to a style.
873
+ * @param {any} nativeMapViewInstance - native map view (com.mapbox.mapboxsdk.maps.MapView)
874
+ *
875
+ * @see MapboxViewCommonBase:setMapStyle()
876
+ *
877
+ * @link https://docs.mapbox.com/android/api/map-sdk/7.1.2/com/mapbox/mapboxsdk/maps/Style.Builder.html
878
+ * @link https://docs.mapbox.com/android/api/map-sdk/7.1.2/com/mapbox/mapboxsdk/maps/MapboxMap.html#setStyle-java.lang.String-com.mapbox.mapboxsdk.maps.Style.OnStyleLoaded-
879
+ */
655
880
  setMapStyle(style, nativeMapViewInstance) {
656
881
  return new Promise((resolve, reject) => {
657
882
  try {
@@ -659,15 +884,31 @@ export class Mapbox extends MapboxCommon {
659
884
  if (Trace.isEnabled()) {
660
885
  CLog(CLogTypes.info, 'setMapStyle(): with style:', style);
661
886
  }
887
+ // callback for when the style is successfully loaded.
662
888
  this.onDidFinishLoadingStyleListener = new com.mapbox.mapboxsdk.maps.MapView.OnDidFinishLoadingStyleListener({
663
889
  onDidFinishLoadingStyle: () => {
664
890
  if (Trace.isEnabled()) {
665
891
  CLog(CLogTypes.info, 'Mapbox:setMapStyle(): style loaded');
666
892
  }
893
+ // FIXME: now that the map is initialized and the style is loaded we can
894
+ // create the annotation managers that allow us to (hopefully) reliably
895
+ // receive events on lines
667
896
  const nMapbox = this._mapboxMapInstance;
668
897
  const nMapView = this._mapboxViewInstance;
669
898
  const nStyle = nMapbox.getStyle();
670
899
  this.lineManager = new com.mapbox.mapboxsdk.plugins.annotation.LineManager(nMapView, nMapbox, nStyle);
900
+ // this.symbolManager = new com.mapbox.mapboxsdk.plugins.annotation.SymbolManager(nMapView, nMapbox, nStyle);
901
+ // this.symbolManager.addClickListener(
902
+ // new com.mapbox.mapboxsdk.plugins.annotation.OnSymbolClickListener({
903
+ // onAnnotationClick: (marker: com.mapbox.mapboxsdk.plugins.annotation.Symbol) => {
904
+ // const cachedMarker = this._getClickedMarkerDetails(marker);
905
+ // if (cachedMarker && cachedMarker.onTap) {
906
+ // cachedMarker.onTap(cachedMarker);
907
+ // }
908
+ // return false;
909
+ // },
910
+ // })
911
+ // );
671
912
  this.onAnnotationClickListener = new com.mapbox.mapboxsdk.plugins.annotation.OnAnnotationClickListener({
672
913
  onAnnotationClick: (line) => {
673
914
  if (Trace.isEnabled()) {
@@ -682,6 +923,7 @@ export class Mapbox extends MapboxCommon {
682
923
  }
683
924
  });
684
925
  this._mapboxViewInstance.addOnDidFinishLoadingStyleListener(this.onDidFinishLoadingStyleListener);
926
+ // callback if loading the style fails.
685
927
  this.onDidFailLoadingMapListener = new com.mapbox.mapboxsdk.maps.MapView.OnDidFailLoadingMapListener({
686
928
  onDidFailLoadingMap: (error) => {
687
929
  if (Trace.isEnabled()) {
@@ -789,6 +1031,11 @@ export class Mapbox extends MapboxCommon {
789
1031
  throw ex;
790
1032
  }
791
1033
  }
1034
+ /**
1035
+ *
1036
+ * @deprecated
1037
+ * @link https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-annotation
1038
+ */
792
1039
  _addMarkers(markers, nativeMap) {
793
1040
  if (!markers) {
794
1041
  if (Trace.isEnabled()) {
@@ -833,6 +1080,7 @@ export class Mapbox extends MapboxCommon {
833
1080
  this.iconFactory = com.mapbox.mapboxsdk.annotations.IconFactory.getInstance(Application.android.context);
834
1081
  }
835
1082
  const iconFactory = this.iconFactory;
1083
+ // if any markers need to be downloaded from the web they need to be available synchronously, so fetch them first before looping
836
1084
  this._downloadMarkerImages(markers).then((updatedMarkers) => {
837
1085
  for (const m in updatedMarkers) {
838
1086
  const marker = updatedMarkers[m];
@@ -842,14 +1090,15 @@ export class Mapbox extends MapboxCommon {
842
1090
  markerOptions.setSnippet(marker.subtitle);
843
1091
  markerOptions.setPosition(new com.mapbox.mapboxsdk.geometry.LatLng(parseFloat(marker.lat), parseFloat(marker.lng)));
844
1092
  if (marker.icon) {
1093
+ // for markers from url see UrlMarker in https://github.com/mapbox/mapbox-gl-native/issues/5370
845
1094
  if (marker.icon.startsWith('res://')) {
846
- let cached = this.iconCache[marker.iconPath];
1095
+ let cached = this.iconCache[marker.icon];
847
1096
  if (!cached) {
848
1097
  const resourcename = marker.icon.substring(6);
849
1098
  const res = Utils.ad.getApplicationContext().getResources();
850
1099
  const identifier = res.getIdentifier(resourcename, 'drawable', Utils.ad.getApplication().getPackageName());
851
1100
  if (identifier !== 0) {
852
- cached = this.iconCache[marker.iconPath] = iconFactory.fromResource(identifier);
1101
+ cached = this.iconCache[marker.icon] = iconFactory.fromResource(identifier);
853
1102
  }
854
1103
  }
855
1104
  if (cached) {
@@ -874,7 +1123,9 @@ export class Mapbox extends MapboxCommon {
874
1123
  let cached = this.iconCache[marker.iconPath];
875
1124
  if (!cached) {
876
1125
  const iconFullPath = path.join(knownFolders.currentApp().path, marker.iconPath.replace('~/', ''));
1126
+ // if the file doesn't exist the app will crash, so checking it
877
1127
  if (File.exists(iconFullPath)) {
1128
+ // could set width, height, retina, see https://github.com/Telerik-Verified-Plugins/Mapbox/pull/42/files?diff=unified&short_path=1c65267, but that's what the marker.icon param is for..
878
1129
  cached = this.iconCache[marker.iconPath] = iconFactory.fromPath(iconFullPath);
879
1130
  }
880
1131
  }
@@ -921,6 +1172,10 @@ export class Mapbox extends MapboxCommon {
921
1172
  }
922
1173
  });
923
1174
  }
1175
+ /**
1176
+ *
1177
+ * @deprecated
1178
+ */
924
1179
  _removeMarkers(ids, nativeMap) {
925
1180
  if (!this._mapboxMapInstance) {
926
1181
  return;
@@ -933,6 +1188,7 @@ export class Mapbox extends MapboxCommon {
933
1188
  }
934
1189
  }
935
1190
  }
1191
+ // remove markers from cache
936
1192
  if (ids) {
937
1193
  this._markers = this._markers.filter((marker) => ids.indexOf(marker.id) === -1);
938
1194
  }
@@ -1053,6 +1309,11 @@ export class Mapbox extends MapboxCommon {
1053
1309
  }
1054
1310
  });
1055
1311
  }
1312
+ /**
1313
+ * get users current location
1314
+ *
1315
+ * @link https://docs.mapbox.com/android/api/map-sdk/9.0.0/com/mapbox/mapboxsdk/location/LocationComponent.html#getLastKnownLocation--
1316
+ */
1056
1317
  getUserLocation() {
1057
1318
  return new Promise((resolve, reject) => {
1058
1319
  try {
@@ -1072,6 +1333,9 @@ export class Mapbox extends MapboxCommon {
1072
1333
  }
1073
1334
  });
1074
1335
  }
1336
+ /**
1337
+ * @link https://www.mapbox.com/android-docs/api/mapbox-java/libjava-geojson/3.4.1/com/mapbox/geojson/Feature.html
1338
+ */
1075
1339
  queryRenderedFeatures(options) {
1076
1340
  return new Promise((resolve, reject) => {
1077
1341
  try {
@@ -1145,6 +1409,10 @@ export class Mapbox extends MapboxCommon {
1145
1409
  }
1146
1410
  });
1147
1411
  }
1412
+ /**
1413
+ *
1414
+ * @deprecated
1415
+ */
1148
1416
  addPolygon(options, nativeMap) {
1149
1417
  return new Promise((resolve, reject) => {
1150
1418
  try {
@@ -1160,6 +1428,7 @@ export class Mapbox extends MapboxCommon {
1160
1428
  }
1161
1429
  polygonOptions.fillColor(Mapbox.getAndroidColor(options.fillColor));
1162
1430
  polygonOptions.alpha(options.fillOpacity === undefined ? 1 : options.fillOpacity);
1431
+ // Note that the stroke is barely visible, see https://github.com/mapbox/mapbox-gl-native/issues/5676
1163
1432
  if (options.strokeColor) {
1164
1433
  polygonOptions.strokeColor(Mapbox.getAndroidColor(options.strokeColor));
1165
1434
  }
@@ -1177,6 +1446,10 @@ export class Mapbox extends MapboxCommon {
1177
1446
  }
1178
1447
  });
1179
1448
  }
1449
+ /**
1450
+ *
1451
+ * @deprecated
1452
+ */
1180
1453
  addPolyline(options, nativeMap) {
1181
1454
  return new Promise((resolve, reject) => {
1182
1455
  try {
@@ -1186,7 +1459,7 @@ export class Mapbox extends MapboxCommon {
1186
1459
  return;
1187
1460
  }
1188
1461
  const polylineOptions = new com.mapbox.mapboxsdk.annotations.PolylineOptions();
1189
- polylineOptions.width(options.width || 5);
1462
+ polylineOptions.width(options.width || 5); // default 5
1190
1463
  polylineOptions.color(Mapbox.getAndroidColor(options.color));
1191
1464
  polylineOptions.alpha(options.opacity === undefined ? 1 : options.opacity);
1192
1465
  for (const p in points) {
@@ -1287,6 +1560,14 @@ export class Mapbox extends MapboxCommon {
1287
1560
  }
1288
1561
  });
1289
1562
  }
1563
+ /**
1564
+ * set an on map click listener.
1565
+ *
1566
+ * The new Mapbox Native SDK allows for multiple listeners on an event and follows the standard
1567
+ * pattern of returning 'true' when a handler has handled the event and others shouldn't.
1568
+ *
1569
+ * Not returning a boolean from the listener function will cause a crash.
1570
+ */
1290
1571
  setOnMapClickListener(listener, nativeMap) {
1291
1572
  return new Promise((resolve, reject) => {
1292
1573
  try {
@@ -1351,15 +1632,15 @@ export class Mapbox extends MapboxCommon {
1351
1632
  CLog(CLogTypes.info, 'setOnMoveBeginListener():');
1352
1633
  }
1353
1634
  this.onMoveListener = new com.mapbox.mapboxsdk.maps.MapboxMap.OnMoveListener({
1354
- onMoveBegin: (detector) => {
1635
+ onMoveBegin: (detector /* MoveGestureDetector */) => {
1355
1636
  const coordinate = this._mapboxMapInstance.getCameraPosition().target;
1356
1637
  return listener({
1357
1638
  lat: coordinate.getLatitude(),
1358
1639
  lng: coordinate.getLongitude()
1359
1640
  });
1360
1641
  },
1361
- onMove: (detector) => { },
1362
- onMoveEnd: (detector) => { }
1642
+ onMove: (detector /* MoveGestureDetector */) => { },
1643
+ onMoveEnd: (detector /* MoveGestureDetector */) => { }
1363
1644
  });
1364
1645
  this._mapboxMapInstance.addOnMoveListener(this.onMoveListener);
1365
1646
  resolve();
@@ -1383,9 +1664,9 @@ export class Mapbox extends MapboxCommon {
1383
1664
  CLog(CLogTypes.info, 'setOnMoveEndListener():');
1384
1665
  }
1385
1666
  this.onMoveListener = new com.mapbox.mapboxsdk.maps.MapboxMap.OnMoveListener({
1386
- onMoveBegin: (detector) => { },
1387
- onMove: (detector) => { },
1388
- onMoveEnd: (detector) => {
1667
+ onMoveBegin: (detector /* MoveGestureDetector */) => { },
1668
+ onMove: (detector /* MoveGestureDetector */) => { },
1669
+ onMoveEnd: (detector /* MoveGestureDetector */) => {
1389
1670
  const coordinate = this._mapboxMapInstance.getCameraPosition().target;
1390
1671
  return listener({
1391
1672
  lat: coordinate.getLatitude(),
@@ -1414,16 +1695,17 @@ export class Mapbox extends MapboxCommon {
1414
1695
  if (Trace.isEnabled()) {
1415
1696
  CLog(CLogTypes.info, 'setOnScrollListener():');
1416
1697
  }
1698
+ // the 'onMove' event seems like the one closest to the iOS implementation
1417
1699
  this.onScrollListener = new com.mapbox.mapboxsdk.maps.MapboxMap.OnMoveListener({
1418
- onMoveBegin: (detector) => { },
1419
- onMove: (detector) => {
1700
+ onMoveBegin: (detector /* MoveGestureDetector */) => { },
1701
+ onMove: (detector /* MoveGestureDetector */) => {
1420
1702
  const coordinate = this._mapboxMapInstance.getCameraPosition().target;
1421
1703
  return listener({
1422
1704
  lat: coordinate.getLatitude(),
1423
1705
  lng: coordinate.getLongitude()
1424
1706
  });
1425
1707
  },
1426
- onMoveEnd: (detector) => { }
1708
+ onMoveEnd: (detector /* MoveGestureDetector */) => { }
1427
1709
  });
1428
1710
  this._mapboxMapInstance.addOnMoveListener(this.onScrollListener);
1429
1711
  resolve();
@@ -1586,7 +1868,10 @@ export class Mapbox extends MapboxCommon {
1586
1868
  .build();
1587
1869
  const retinaFactor = Utils.layout.getDisplayDensity();
1588
1870
  const offlineRegionDefinition = new com.mapbox.mapboxsdk.offline.OfflineTilePyramidRegionDefinition(styleURL, bounds, options.minZoom, options.maxZoom, retinaFactor);
1589
- const info = Object.assign({ name: options.name }, options.metadata);
1871
+ const info = {
1872
+ name: options.name,
1873
+ ...options.metadata
1874
+ };
1590
1875
  const infoStr = new java.lang.String(JSON.stringify(info));
1591
1876
  const encodedMetadata = infoStr.getBytes();
1592
1877
  if (!this._accessToken && !options.accessToken) {
@@ -1602,9 +1887,14 @@ export class Mapbox extends MapboxCommon {
1602
1887
  reject(error);
1603
1888
  },
1604
1889
  onCreate: (offlineRegion) => {
1890
+ // if (options.onCreate) {
1891
+ // options.onCreate(offlineRegion);
1892
+ // }
1605
1893
  offlineRegion.setDownloadState(com.mapbox.mapboxsdk.offline.OfflineRegion.STATE_ACTIVE);
1894
+ // Monitor the download progress using setObserver
1606
1895
  offlineRegion.setObserver(new com.mapbox.mapboxsdk.offline.OfflineRegion.OfflineRegionObserver({
1607
1896
  onStatusChanged: (status) => {
1897
+ // Calculate the download percentage and update the progress bar
1608
1898
  const percentage = status.getRequiredResourceCount() >= 0 ? (100.0 * status.getCompletedResourceCount()) / status.getRequiredResourceCount() : 0.0;
1609
1899
  if (options.onProgress) {
1610
1900
  options.onProgress({
@@ -1613,6 +1903,7 @@ export class Mapbox extends MapboxCommon {
1613
1903
  completed: status.getCompletedResourceCount(),
1614
1904
  expected: status.getRequiredResourceCount(),
1615
1905
  percentage: Math.round(percentage * 100) / 100,
1906
+ // downloading: status.getDownloadState() == com.mapbox.mapboxsdk.offline.OfflineRegion.STATE_ACTIVE,
1616
1907
  complete: status.isComplete()
1617
1908
  });
1618
1909
  }
@@ -1720,8 +2011,10 @@ export class Mapbox extends MapboxCommon {
1720
2011
  },
1721
2012
  onDelete: () => {
1722
2013
  resolve();
2014
+ // don't return, see note below
1723
2015
  }
1724
2016
  }));
2017
+ // don't break the loop as there may be multiple packs with the same name
1725
2018
  }
1726
2019
  }
1727
2020
  }
@@ -1748,6 +2041,7 @@ export class Mapbox extends MapboxCommon {
1748
2041
  addExtrusion(options, nativeMap) {
1749
2042
  return new Promise((resolve, reject) => {
1750
2043
  try {
2044
+ // Create fill extrusion layer
1751
2045
  const fillExtrusionLayer = new com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer('3d-buildings', 'composite');
1752
2046
  fillExtrusionLayer.setSourceLayer('building');
1753
2047
  fillExtrusionLayer.setFilter(com.mapbox.mapboxsdk.style.expressions.Expression.eq(com.mapbox.mapboxsdk.style.expressions.Expression.get('extrude'), 'true'));
@@ -1757,6 +2051,7 @@ export class Mapbox extends MapboxCommon {
1757
2051
  props[1] = com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionHeight(com.mapbox.mapboxsdk.style.expressions.Expression.get('height'));
1758
2052
  props[2] = com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionBase(com.mapbox.mapboxsdk.style.expressions.Expression.get('min_height'));
1759
2053
  props[3] = com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionOpacity(com.mapbox.mapboxsdk.style.expressions.Expression.literal(0.6));
2054
+ // Set data-driven styling properties
1760
2055
  fillExtrusionLayer.setProperties(props);
1761
2056
  this._mapboxMapInstance.getStyle().addLayer(fillExtrusionLayer);
1762
2057
  resolve();
@@ -1769,6 +2064,10 @@ export class Mapbox extends MapboxCommon {
1769
2064
  }
1770
2065
  });
1771
2066
  }
2067
+ /**
2068
+ * update a geojson source
2069
+ *
2070
+ */
1772
2071
  updateSource(id, options, nativeMap) {
1773
2072
  return new Promise((resolve, reject) => {
1774
2073
  try {
@@ -1801,6 +2100,14 @@ export class Mapbox extends MapboxCommon {
1801
2100
  }
1802
2101
  });
1803
2102
  }
2103
+ /**
2104
+ * add a geojson or vector source
2105
+ *
2106
+ * Add a source that can then be referenced in the style specification
2107
+ * passed to addLayer().
2108
+ *
2109
+ * @link https://docs.mapbox.com/mapbox-gl-js/api/#map#addsource
2110
+ */
1804
2111
  addSource(id, options, nativeMap) {
1805
2112
  return new Promise((resolve, reject) => {
1806
2113
  try {
@@ -1879,6 +2186,7 @@ export class Mapbox extends MapboxCommon {
1879
2186
  break;
1880
2187
  }
1881
2188
  case 'raster':
2189
+ // use Array.create because a marshal error throws on TileSet if options.tiles directly passed.
1882
2190
  const tiles = Array.create(java.lang.String, options.tiles.length);
1883
2191
  options.tiles.forEach((val, i) => (tiles[i] = val));
1884
2192
  const tileSet = new com.mapbox.mapboxsdk.style.sources.TileSet('2.0.0', tiles);
@@ -1919,6 +2227,9 @@ export class Mapbox extends MapboxCommon {
1919
2227
  }
1920
2228
  });
1921
2229
  }
2230
+ /**
2231
+ * remove source by id
2232
+ */
1922
2233
  removeSource(id, nativeMap) {
1923
2234
  return new Promise((resolve, reject) => {
1924
2235
  try {
@@ -1941,6 +2252,24 @@ export class Mapbox extends MapboxCommon {
1941
2252
  }
1942
2253
  });
1943
2254
  }
2255
+ /**
2256
+ * a rough analogue to the mapbox-gl-js addLayer() method
2257
+ *
2258
+ * It would be nice if this {N} API matched the mapbox-gl-js API which
2259
+ * would make it much easier to share mapping applications between the web
2260
+ * and {N} apps.
2261
+ *
2262
+ * This method accepts a Mapbox-GL-JS style specification JSON object with some
2263
+ * limitations:
2264
+ *
2265
+ * - the source: must be a GeoJSON object, vector source definition, or an id of a source added via addSource()
2266
+ * - only a subset of paint properties are available.
2267
+ *
2268
+ * @param {object} style - a style following the Mapbox style specification.
2269
+ * @param {any} nativeMapView - native map view (com.mapbox.mapboxsdk.maps.MapView)
2270
+ *
2271
+ * @link https://docs.mapbox.com/mapbox-gl-js/style-spec/#layers
2272
+ */
1944
2273
  async addLayer(style, belowLayerId, nativeMap) {
1945
2274
  const theMap = nativeMap || this._mapboxMapInstance;
1946
2275
  if (!theMap) {
@@ -1961,6 +2290,13 @@ export class Mapbox extends MapboxCommon {
1961
2290
  }
1962
2291
  this._mapboxMapInstance.getStyle().addLayer(layer.getNativeInstance());
1963
2292
  }
2293
+ /**
2294
+ * remove layer by ID
2295
+ *
2296
+ * Removes a layer given a layer id
2297
+ *
2298
+ * @param {string} id
2299
+ */
1964
2300
  async removeLayer(id, nativeMap) {
1965
2301
  const theMap = nativeMap || this._mapboxMapInstance;
1966
2302
  theMap.getStyle().removeLayer(id);
@@ -1968,6 +2304,19 @@ export class Mapbox extends MapboxCommon {
1968
2304
  CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer');
1969
2305
  }
1970
2306
  }
2307
+ /**
2308
+ * @deprecated
2309
+ * Add a point to a line
2310
+ *
2311
+ * This method appends a point to a line and is useful for drawing a users track.
2312
+ *
2313
+ * @param {id} id - id of line to add a point to.
2314
+ * @param {array} lnglat - [lng,lat] to append to the line.
2315
+ *
2316
+ * @link https://github.com/mapbox/mapbox-gl-native/issues/13983
2317
+ * @link https://docs.mapbox.com/android/api/mapbox-java/libjava-geojson/3.0.1/com/mapbox/geojson/Feature.html#Feature--
2318
+ * @link https://docs.oracle.com/javase/8/docs/api/java/util/List.html
2319
+ */
1971
2320
  async addLinePoint(id, lnglat, sourceId, nativeMapView) {
1972
2321
  try {
1973
2322
  const sId = !!sourceId ? sourceId : id + '_source';
@@ -1999,6 +2348,7 @@ export class Mapbox extends MapboxCommon {
1999
2348
  const layers = [];
2000
2349
  if (options.clusters) {
2001
2350
  for (let i = 0; i < options.clusters.length; i++) {
2351
+ // TODO also allow Color object
2002
2352
  layers.push([options.clusters[i].points, new Color(options.clusters[i].color).android]);
2003
2353
  }
2004
2354
  }
@@ -2014,10 +2364,12 @@ export class Mapbox extends MapboxCommon {
2014
2364
  com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleBlur(new java.lang.Float(0.2))
2015
2365
  ]);
2016
2366
  unclustered.setFilter(com.mapbox.mapboxsdk.style.expressions.Expression.neq(com.mapbox.mapboxsdk.style.expressions.Expression.get('cluster'), true));
2017
- this._mapboxMapInstance.getStyle().addLayer(unclustered);
2367
+ this._mapboxMapInstance.getStyle().addLayer(unclustered); // , "building");
2018
2368
  for (let i = 0; i < layers.length; i++) {
2369
+ // Add some nice circles
2019
2370
  const circles = new com.mapbox.mapboxsdk.style.layers.CircleLayer('cluster-' + i, options.name);
2020
2371
  circles.setProperties([
2372
+ // com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage("icon")
2021
2373
  com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor(layers[i][1]),
2022
2374
  com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius(new java.lang.Float(22.0)),
2023
2375
  com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleBlur(new java.lang.Float(0.2))
@@ -2032,8 +2384,9 @@ export class Mapbox extends MapboxCommon {
2032
2384
  com.mapbox.mapboxsdk.style.expressions.Expression.lt(pointCount, com.mapbox.mapboxsdk.style.expressions.Expression.literal(java.lang.Integer.valueOf(layers[i - 1][0])))
2033
2385
  ]));
2034
2386
  }
2035
- this._mapboxMapInstance.getStyle().addLayer(circles);
2387
+ this._mapboxMapInstance.getStyle().addLayer(circles); // , "building");
2036
2388
  }
2389
+ // Add the count labels (note that this doesn't show.. #sad)
2037
2390
  const count = new com.mapbox.mapboxsdk.style.layers.SymbolLayer('count', options.name);
2038
2391
  count.setProperties([
2039
2392
  com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField(com.mapbox.mapboxsdk.style.expressions.Expression.get('point_count')),
@@ -2051,6 +2404,9 @@ export class Mapbox extends MapboxCommon {
2051
2404
  }
2052
2405
  });
2053
2406
  }
2407
+ /**
2408
+ * constantly center the map on the users location.
2409
+ */
2054
2410
  trackUser(options, nativeMap) {
2055
2411
  if (Trace.isEnabled()) {
2056
2412
  CLog(CLogTypes.info, 'trackUser(): top');
@@ -2100,6 +2456,7 @@ export class Mapbox extends MapboxCommon {
2100
2456
  CLog(CLogTypes.info, '_getMapStyle(): top with input:', input);
2101
2457
  }
2102
2458
  const Style = com.mapbox.mapboxsdk.maps.Style;
2459
+ // allow for a style URL to be passed
2103
2460
  if (input.startsWith('mapbox://styles') || input.startsWith('http://') || input.startsWith('https://')) {
2104
2461
  return input;
2105
2462
  }
@@ -2128,9 +2485,17 @@ export class Mapbox extends MapboxCommon {
2128
2485
  return Style.TRAFFIC_NIGHT;
2129
2486
  }
2130
2487
  else {
2488
+ // default
2131
2489
  return Style.MAPBOX_STREETS;
2132
2490
  }
2133
2491
  }
2492
+ /**
2493
+ * Mapbox Map Options
2494
+ *
2495
+ * @link https://github.com/mapbox/mapbox-gl-native/wiki/Android-6.x-to-7.x-migration-guide
2496
+ * @link https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
2497
+ * @link https://docs.mapbox.com/android/api/map-sdk/7.1.2/com/mapbox/mapboxsdk/maps/MapboxMapOptions.html
2498
+ */
2134
2499
  _getMapboxMapOptions(settings) {
2135
2500
  const mapboxMapOptions = new com.mapbox.mapboxsdk.maps.MapboxMapOptions()
2136
2501
  .compassEnabled(!settings.hideCompass)
@@ -2140,7 +2505,9 @@ export class Mapbox extends MapboxCommon {
2140
2505
  .zoomGesturesEnabled(!settings.disableZoom)
2141
2506
  .attributionEnabled(!settings.hideAttribution)
2142
2507
  .logoEnabled(!settings.hideLogo);
2508
+ // zoomlevel is not applied unless center is set
2143
2509
  if (settings.zoomLevel && !settings.center) {
2510
+ // Eiffel tower, Paris
2144
2511
  settings.center = {
2145
2512
  lat: 48.858093,
2146
2513
  lng: 2.294694
@@ -2154,6 +2521,11 @@ export class Mapbox extends MapboxCommon {
2154
2521
  }
2155
2522
  return mapboxMapOptions;
2156
2523
  }
2524
+ /**
2525
+ * convert string to camera mode constant.
2526
+ *
2527
+ * @link https://docs.mapbox.com/android/api/map-sdk/8.1.0/com/mapbox/mapboxsdk/location/modes/CameraMode.html
2528
+ */
2157
2529
  _stringToCameraMode(mode) {
2158
2530
  const modeRef = com.mapbox.mapboxsdk.location.modes.CameraMode;
2159
2531
  switch (mode) {
@@ -2173,6 +2545,9 @@ export class Mapbox extends MapboxCommon {
2173
2545
  return modeRef.TRACKING_GPS_NORTH;
2174
2546
  }
2175
2547
  }
2548
+ /**
2549
+ * convert string to render mode
2550
+ */
2176
2551
  _stringToRenderMode(mode) {
2177
2552
  let renderMode;
2178
2553
  switch (mode) {
@@ -2209,7 +2584,7 @@ export class Mapbox extends MapboxCommon {
2209
2584
  return "NONE";
2210
2585
  }
2211
2586
  _fineLocationPermissionGranted() {
2212
- let hasPermission = android.os.Build.VERSION.SDK_INT < 23;
2587
+ let hasPermission = android.os.Build.VERSION.SDK_INT < 23; // Android M. (6.0)
2213
2588
  if (!hasPermission) {
2214
2589
  hasPermission = com.mapbox.android.core.permissions.PermissionsManager.areLocationPermissionsGranted(Application.android.context);
2215
2590
  }
@@ -2232,6 +2607,33 @@ export class Mapbox extends MapboxCommon {
2232
2607
  const jsonObj = new org.json.JSONObject(jsonStr);
2233
2608
  return JSON.parse(jsonObj.toString());
2234
2609
  }
2610
+ /**
2611
+ * show a user location marker
2612
+ *
2613
+ * This method must not be called before location permissions have been granted.
2614
+ *
2615
+ * Supported options are:
2616
+ *
2617
+ * - foregroundTintColor
2618
+ * - foregroundStaleTintColor
2619
+ * - backgroundTintColor
2620
+ * - bearingTintColor
2621
+ * - elevation
2622
+ * - accuracyColor
2623
+ * - accuracyAlpha
2624
+ * - useDefaultLocationEngine
2625
+ * - renderMode
2626
+ * - cameraMode
2627
+ * - clickListener
2628
+ * - cameraTrackingChangeListener
2629
+ *
2630
+ * @param {object} options
2631
+ *
2632
+ * @link https://github.com/mapbox/mapbox-android-demo/blob/master/MapboxAndroidDemo/src/main/java/com/mapbox/mapboxandroiddemo/examples/location/LocationComponentOptionsActivity.java
2633
+ * @link https://developer.android.com/reference/android/graphics/Color
2634
+ *
2635
+ * @todo at least with simulated data, the location is only updated once hence adding support for forceLocation method.
2636
+ */
2235
2637
  showUserLocationMarker(options, nativeMap) {
2236
2638
  return new Promise((resolve, reject) => {
2237
2639
  try {
@@ -2321,6 +2723,11 @@ export class Mapbox extends MapboxCommon {
2321
2723
  }
2322
2724
  });
2323
2725
  }
2726
+ /**
2727
+ * hide (destroy) the user location marker
2728
+ *
2729
+ * This method destroys the user location marker.
2730
+ */
2324
2731
  hideUserLocationMarker(nativeMap) {
2325
2732
  return new Promise((resolve, reject) => {
2326
2733
  try {
@@ -2349,6 +2756,15 @@ export class Mapbox extends MapboxCommon {
2349
2756
  }
2350
2757
  });
2351
2758
  }
2759
+ /**
2760
+ * Change the mode of the user location marker
2761
+ *
2762
+ * Used to change the camera tracking and render modes of an existing
2763
+ * marker.
2764
+ *
2765
+ * The marker must be configured using showUserLocationMarker before this method
2766
+ * can called.
2767
+ */
2352
2768
  changeUserLocationMarkerMode(renderModeString, cameraModeString, nativeMap) {
2353
2769
  return new Promise((resolve, reject) => {
2354
2770
  try {
@@ -2387,6 +2803,13 @@ export class Mapbox extends MapboxCommon {
2387
2803
  }
2388
2804
  });
2389
2805
  }
2806
+ /**
2807
+ * force updating of user location
2808
+ *
2809
+ * This method forces the user location marker, if displayed, to move to a new location
2810
+ *
2811
+ * @todo figure out why the user location marker is not updating.
2812
+ */
2390
2813
  forceUserLocationUpdate(location, nativeMap) {
2391
2814
  return new Promise((resolve, reject) => {
2392
2815
  try {
@@ -2397,6 +2820,7 @@ export class Mapbox extends MapboxCommon {
2397
2820
  reject('No location component has been loaded');
2398
2821
  return;
2399
2822
  }
2823
+ // the location object needs to be converted into an android location
2400
2824
  const nativeLocation = new android.location.Location('background');
2401
2825
  nativeLocation.setLatitude(location.latitude);
2402
2826
  nativeLocation.setLongitude(location.longitude);
@@ -2467,9 +2891,14 @@ export class Mapbox extends MapboxCommon {
2467
2891
  _getClickedMarkerDetails(clicked) {
2468
2892
  for (const m in this._markers) {
2469
2893
  const cached = this._markers[m];
2470
- if (cached.lat == clicked.getPosition().getLatitude() &&
2894
+ if (
2895
+ // eslint-disable-next-line eqeqeq
2896
+ cached.lat == clicked.getPosition().getLatitude() &&
2897
+ // eslint-disable-next-line eqeqeq
2471
2898
  cached.lng == clicked.getPosition().getLongitude() &&
2472
- cached.title == clicked.getTitle() &&
2899
+ // eslint-disable-next-line eqeqeq
2900
+ cached.title == clicked.getTitle() && // == because of null vs undefined
2901
+ // eslint-disable-next-line eqeqeq
2473
2902
  cached.subtitle == clicked.getSnippet()) {
2474
2903
  return cached;
2475
2904
  }
@@ -2477,11 +2906,13 @@ export class Mapbox extends MapboxCommon {
2477
2906
  }
2478
2907
  _downloadImage(marker) {
2479
2908
  return new Promise((resolve, reject) => {
2909
+ // to cache..
2480
2910
  if (this._markerIconDownloadCache[marker.icon]) {
2481
2911
  marker.iconDownloaded = this._markerIconDownloadCache[marker.icon];
2482
2912
  resolve(marker);
2483
2913
  return;
2484
2914
  }
2915
+ // ..or not to cache
2485
2916
  Http.getImage(marker.icon).then((output) => {
2486
2917
  marker.iconDownloaded = output.android;
2487
2918
  this._markerIconDownloadCache[marker.icon] = marker.iconDownloaded;