@lugg/maps 1.0.0-beta.3 → 1.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +3 -0
  2. package/android/src/main/java/com/luggmaps/LuggCircleView.kt +85 -0
  3. package/android/src/main/java/com/luggmaps/LuggCircleViewManager.kt +79 -0
  4. package/android/src/main/java/com/luggmaps/LuggGroundOverlayView.kt +81 -0
  5. package/android/src/main/java/com/luggmaps/LuggGroundOverlayViewManager.kt +82 -0
  6. package/android/src/main/java/com/luggmaps/LuggMapView.kt +9 -0
  7. package/android/src/main/java/com/luggmaps/LuggPackage.kt +4 -1
  8. package/android/src/main/java/com/luggmaps/LuggTileOverlayView.kt +92 -0
  9. package/android/src/main/java/com/luggmaps/LuggTileOverlayViewManager.kt +80 -0
  10. package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +289 -0
  11. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +9 -0
  12. package/android/src/main/java/com/luggmaps/events/CirclePressEvent.kt +12 -0
  13. package/android/src/main/java/com/luggmaps/events/GroundOverlayPressEvent.kt +12 -0
  14. package/android/src/main/java/com/luggmaps/events/TileOverlayPressEvent.kt +12 -0
  15. package/ios/LuggCircleView.h +31 -0
  16. package/ios/LuggCircleView.mm +133 -0
  17. package/ios/LuggGroundOverlayView.h +30 -0
  18. package/ios/LuggGroundOverlayView.mm +125 -0
  19. package/ios/LuggMapView.mm +43 -0
  20. package/ios/LuggTileOverlayView.h +31 -0
  21. package/ios/LuggTileOverlayView.mm +130 -0
  22. package/ios/core/AppleMapProvider.mm +398 -1
  23. package/ios/core/GoogleMapProvider.mm +299 -10
  24. package/ios/core/MapProviderDelegate.h +12 -0
  25. package/ios/events/CirclePressEvent.h +20 -0
  26. package/ios/events/GroundOverlayPressEvent.h +20 -0
  27. package/ios/events/TileOverlayPressEvent.h +20 -0
  28. package/lib/module/components/Circle.js +46 -0
  29. package/lib/module/components/Circle.js.map +1 -0
  30. package/lib/module/components/Circle.types.js +4 -0
  31. package/lib/module/components/Circle.types.js.map +1 -0
  32. package/lib/module/components/Circle.web.js +79 -0
  33. package/lib/module/components/Circle.web.js.map +1 -0
  34. package/lib/module/components/GroundOverlay.js +45 -0
  35. package/lib/module/components/GroundOverlay.js.map +1 -0
  36. package/lib/module/components/GroundOverlay.types.js +4 -0
  37. package/lib/module/components/GroundOverlay.types.js.map +1 -0
  38. package/lib/module/components/GroundOverlay.web.js +77 -0
  39. package/lib/module/components/GroundOverlay.web.js.map +1 -0
  40. package/lib/module/components/Marker.js +5 -1
  41. package/lib/module/components/Marker.js.map +1 -1
  42. package/lib/module/components/TileOverlay.js +44 -0
  43. package/lib/module/components/TileOverlay.js.map +1 -0
  44. package/lib/module/components/TileOverlay.types.js +4 -0
  45. package/lib/module/components/TileOverlay.types.js.map +1 -0
  46. package/lib/module/components/TileOverlay.web.js +69 -0
  47. package/lib/module/components/TileOverlay.web.js.map +1 -0
  48. package/lib/module/components/index.js +3 -0
  49. package/lib/module/components/index.js.map +1 -1
  50. package/lib/module/components/index.web.js +3 -0
  51. package/lib/module/components/index.web.js.map +1 -1
  52. package/lib/module/fabric/LuggCircleViewNativeComponent.ts +25 -0
  53. package/lib/module/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
  54. package/lib/module/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
  55. package/lib/module/index.js +3 -0
  56. package/lib/module/index.js.map +1 -1
  57. package/lib/module/index.web.js +3 -0
  58. package/lib/module/index.web.js.map +1 -1
  59. package/lib/typescript/src/components/Circle.d.ts +10 -0
  60. package/lib/typescript/src/components/Circle.d.ts.map +1 -0
  61. package/lib/typescript/src/components/Circle.types.d.ts +33 -0
  62. package/lib/typescript/src/components/Circle.types.d.ts.map +1 -0
  63. package/lib/typescript/src/components/Circle.web.d.ts +3 -0
  64. package/lib/typescript/src/components/Circle.web.d.ts.map +1 -0
  65. package/lib/typescript/src/components/GroundOverlay.d.ts +10 -0
  66. package/lib/typescript/src/components/GroundOverlay.d.ts.map +1 -0
  67. package/lib/typescript/src/components/GroundOverlay.types.d.ts +35 -0
  68. package/lib/typescript/src/components/GroundOverlay.types.d.ts.map +1 -0
  69. package/lib/typescript/src/components/GroundOverlay.web.d.ts +3 -0
  70. package/lib/typescript/src/components/GroundOverlay.web.d.ts.map +1 -0
  71. package/lib/typescript/src/components/Marker.d.ts.map +1 -1
  72. package/lib/typescript/src/components/Marker.types.d.ts +4 -1
  73. package/lib/typescript/src/components/Marker.types.d.ts.map +1 -1
  74. package/lib/typescript/src/components/TileOverlay.d.ts +10 -0
  75. package/lib/typescript/src/components/TileOverlay.d.ts.map +1 -0
  76. package/lib/typescript/src/components/TileOverlay.types.d.ts +36 -0
  77. package/lib/typescript/src/components/TileOverlay.types.d.ts.map +1 -0
  78. package/lib/typescript/src/components/TileOverlay.web.d.ts +3 -0
  79. package/lib/typescript/src/components/TileOverlay.web.d.ts.map +1 -0
  80. package/lib/typescript/src/components/index.d.ts +6 -0
  81. package/lib/typescript/src/components/index.d.ts.map +1 -1
  82. package/lib/typescript/src/components/index.web.d.ts +6 -0
  83. package/lib/typescript/src/components/index.web.d.ts.map +1 -1
  84. package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts +18 -0
  85. package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts.map +1 -0
  86. package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts +21 -0
  87. package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts.map +1 -0
  88. package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts +21 -0
  89. package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts.map +1 -0
  90. package/lib/typescript/src/index.d.ts +6 -0
  91. package/lib/typescript/src/index.d.ts.map +1 -1
  92. package/lib/typescript/src/index.web.d.ts +6 -0
  93. package/lib/typescript/src/index.web.d.ts.map +1 -1
  94. package/package.json +5 -2
  95. package/src/components/Circle.tsx +52 -0
  96. package/src/components/Circle.types.ts +33 -0
  97. package/src/components/Circle.web.tsx +93 -0
  98. package/src/components/GroundOverlay.tsx +47 -0
  99. package/src/components/GroundOverlay.types.ts +36 -0
  100. package/src/components/GroundOverlay.web.tsx +85 -0
  101. package/src/components/Marker.tsx +4 -1
  102. package/src/components/Marker.types.ts +4 -1
  103. package/src/components/TileOverlay.tsx +44 -0
  104. package/src/components/TileOverlay.types.ts +37 -0
  105. package/src/components/TileOverlay.web.tsx +95 -0
  106. package/src/components/index.ts +9 -0
  107. package/src/components/index.web.ts +9 -0
  108. package/src/fabric/LuggCircleViewNativeComponent.ts +25 -0
  109. package/src/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
  110. package/src/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
  111. package/src/index.ts +6 -0
  112. package/src/index.web.ts +12 -0
@@ -14,13 +14,25 @@ import com.google.android.gms.maps.OnMapReadyCallback
14
14
  import com.google.android.gms.maps.model.AdvancedMarker
15
15
  import com.google.android.gms.maps.model.AdvancedMarkerOptions
16
16
  import com.google.android.gms.maps.model.BitmapDescriptorFactory
17
+ import com.google.android.gms.maps.model.Circle
18
+ import com.google.android.gms.maps.model.CircleOptions
19
+ import com.google.android.gms.maps.model.GroundOverlay
20
+ import com.google.android.gms.maps.model.GroundOverlayOptions
17
21
  import com.google.android.gms.maps.model.LatLng
22
+ import com.google.android.gms.maps.model.LatLngBounds
18
23
  import com.google.android.gms.maps.model.MapColorScheme
19
24
  import com.google.android.gms.maps.model.Marker
20
25
  import com.google.android.gms.maps.model.Polygon
21
26
  import com.google.android.gms.maps.model.PolygonOptions
22
27
  import com.google.android.gms.maps.model.PolylineOptions
28
+ import com.google.android.gms.maps.model.TileOverlay
29
+ import com.google.android.gms.maps.model.TileOverlayOptions
30
+ import com.google.android.gms.maps.model.UrlTileProvider
23
31
  import com.luggmaps.LuggCalloutView
32
+ import com.luggmaps.LuggCircleView
33
+ import com.luggmaps.LuggCircleViewDelegate
34
+ import com.luggmaps.LuggGroundOverlayView
35
+ import com.luggmaps.LuggGroundOverlayViewDelegate
24
36
  import com.luggmaps.LuggMapWrapperView
25
37
  import com.luggmaps.LuggMarkerView
26
38
  import com.luggmaps.LuggMarkerViewDelegate
@@ -28,6 +40,9 @@ import com.luggmaps.LuggPolygonView
28
40
  import com.luggmaps.LuggPolygonViewDelegate
29
41
  import com.luggmaps.LuggPolylineView
30
42
  import com.luggmaps.LuggPolylineViewDelegate
43
+ import com.luggmaps.LuggTileOverlayView
44
+ import com.luggmaps.LuggTileOverlayViewDelegate
45
+ import java.net.URL
31
46
 
32
47
  class GoogleMapProvider(private val context: Context) :
33
48
  MapProvider,
@@ -35,12 +50,17 @@ class GoogleMapProvider(private val context: Context) :
35
50
  LuggMarkerViewDelegate,
36
51
  LuggPolylineViewDelegate,
37
52
  LuggPolygonViewDelegate,
53
+ LuggCircleViewDelegate,
54
+ LuggGroundOverlayViewDelegate,
55
+ LuggTileOverlayViewDelegate,
38
56
  GoogleMap.OnCameraMoveStartedListener,
39
57
  GoogleMap.OnCameraMoveListener,
40
58
  GoogleMap.OnCameraIdleListener,
41
59
  GoogleMap.OnMapClickListener,
42
60
  GoogleMap.OnMapLongClickListener,
43
61
  GoogleMap.OnPolygonClickListener,
62
+ GoogleMap.OnCircleClickListener,
63
+ GoogleMap.OnGroundOverlayClickListener,
44
64
  GoogleMap.OnMarkerClickListener,
45
65
  GoogleMap.OnMarkerDragListener,
46
66
  GoogleMap.InfoWindowAdapter {
@@ -58,8 +78,13 @@ class GoogleMapProvider(private val context: Context) :
58
78
  private val pendingMarkerViews = mutableSetOf<LuggMarkerView>()
59
79
  private val pendingPolylineViews = mutableSetOf<LuggPolylineView>()
60
80
  private val pendingPolygonViews = mutableSetOf<LuggPolygonView>()
81
+ private val pendingCircleViews = mutableSetOf<LuggCircleView>()
82
+ private val pendingGroundOverlayViews = mutableSetOf<LuggGroundOverlayView>()
83
+ private val pendingTileOverlayViews = mutableSetOf<LuggTileOverlayView>()
61
84
  private val polylineAnimators = mutableMapOf<LuggPolylineView, PolylineAnimator>()
62
85
  private val polygonToViewMap = mutableMapOf<Polygon, LuggPolygonView>()
86
+ private val circleToViewMap = mutableMapOf<Circle, LuggCircleView>()
87
+ private val groundOverlayToViewMap = mutableMapOf<GroundOverlay, LuggGroundOverlayView>()
63
88
  private val markerToViewMap = mutableMapOf<Marker, LuggMarkerView>()
64
89
  private val liveMarkerViews = mutableSetOf<LuggMarkerView>()
65
90
  private var activeNonBubbledMarker: Marker? = null
@@ -118,9 +143,14 @@ class GoogleMapProvider(private val context: Context) :
118
143
  pendingMarkerViews.clear()
119
144
  pendingPolylineViews.clear()
120
145
  pendingPolygonViews.clear()
146
+ pendingCircleViews.clear()
147
+ pendingGroundOverlayViews.clear()
148
+ pendingTileOverlayViews.clear()
121
149
  polylineAnimators.values.forEach { it.destroy() }
122
150
  polylineAnimators.clear()
123
151
  polygonToViewMap.clear()
152
+ circleToViewMap.clear()
153
+ groundOverlayToViewMap.clear()
124
154
  markerToViewMap.clear()
125
155
  wrapperView?.touchEventHandler = null
126
156
  wrapperView = null
@@ -130,6 +160,8 @@ class GoogleMapProvider(private val context: Context) :
130
160
  googleMap?.setOnMapClickListener(null)
131
161
  googleMap?.setOnMapLongClickListener(null)
132
162
  googleMap?.setOnPolygonClickListener(null)
163
+ googleMap?.setOnCircleClickListener(null)
164
+ googleMap?.setOnGroundOverlayClickListener(null)
133
165
  googleMap?.setOnMarkerClickListener(null)
134
166
  googleMap?.setOnMarkerDragListener(null)
135
167
  googleMap?.setInfoWindowAdapter(null)
@@ -154,6 +186,8 @@ class GoogleMapProvider(private val context: Context) :
154
186
  map.setOnMapClickListener(this)
155
187
  map.setOnMapLongClickListener(this)
156
188
  map.setOnPolygonClickListener(this)
189
+ map.setOnCircleClickListener(this)
190
+ map.setOnGroundOverlayClickListener(this)
157
191
  map.setOnMarkerClickListener(this)
158
192
  map.setOnMarkerDragListener(this)
159
193
  map.setInfoWindowAdapter(this)
@@ -172,6 +206,9 @@ class GoogleMapProvider(private val context: Context) :
172
206
  processPendingMarkers()
173
207
  processPendingPolylines()
174
208
  processPendingPolygons()
209
+ processPendingCircles()
210
+ processPendingGroundOverlays()
211
+ processPendingTileOverlays()
175
212
 
176
213
  delegate?.mapProviderDidReady()
177
214
  }
@@ -227,6 +264,22 @@ class GoogleMapProvider(private val context: Context) :
227
264
  }
228
265
  }
229
266
 
267
+ override fun onCircleClick(circle: Circle) {
268
+ val circleView = circleToViewMap[circle]
269
+ if (circleView?.tappable == true) {
270
+ circleView.emitPressEvent()
271
+ } else {
272
+ onMapClick(tapLocation ?: return)
273
+ }
274
+ }
275
+
276
+ override fun onGroundOverlayClick(groundOverlay: GroundOverlay) {
277
+ val view = groundOverlayToViewMap[groundOverlay]
278
+ if (view?.tappable == true) {
279
+ view.emitPressEvent()
280
+ }
281
+ }
282
+
230
283
  override fun onMarkerClick(marker: Marker): Boolean {
231
284
  dismissNonBubbledCallout()
232
285
 
@@ -487,6 +540,30 @@ class GoogleMapProvider(private val context: Context) :
487
540
 
488
541
  // endregion
489
542
 
543
+ // region CircleViewDelegate
544
+
545
+ override fun circleViewDidUpdate(circleView: LuggCircleView) {
546
+ syncCircleView(circleView)
547
+ }
548
+
549
+ // endregion
550
+
551
+ // region GroundOverlayViewDelegate
552
+
553
+ override fun groundOverlayViewDidUpdate(groundOverlayView: LuggGroundOverlayView) {
554
+ syncGroundOverlayView(groundOverlayView)
555
+ }
556
+
557
+ // endregion
558
+
559
+ // region TileOverlayViewDelegate
560
+
561
+ override fun tileOverlayViewDidUpdate(tileOverlayView: LuggTileOverlayView) {
562
+ syncTileOverlayView(tileOverlayView)
563
+ }
564
+
565
+ // endregion
566
+
490
567
  // region Marker Management
491
568
 
492
569
  override fun addMarkerView(markerView: LuggMarkerView) {
@@ -753,6 +830,218 @@ class GoogleMapProvider(private val context: Context) :
753
830
 
754
831
  // endregion
755
832
 
833
+ // region Circle Management
834
+
835
+ override fun addCircleView(circleView: LuggCircleView) {
836
+ circleView.delegate = this
837
+ syncCircleView(circleView)
838
+ }
839
+
840
+ override fun removeCircleView(circleView: LuggCircleView) {
841
+ circleView.circle?.let { circleToViewMap.remove(it) }
842
+ circleView.circle?.remove()
843
+ circleView.circle = null
844
+ }
845
+
846
+ private fun syncCircleView(circleView: LuggCircleView) {
847
+ if (googleMap == null) {
848
+ pendingCircleViews.add(circleView)
849
+ return
850
+ }
851
+
852
+ if (circleView.circle == null) {
853
+ addCircleViewToMap(circleView)
854
+ return
855
+ }
856
+
857
+ circleView.circle?.apply {
858
+ center = circleView.center
859
+ radius = circleView.radius
860
+ fillColor = circleView.fillColor
861
+ strokeColor = circleView.strokeColor
862
+ strokeWidth = circleView.strokeWidth.dpToPx()
863
+ zIndex = circleView.zIndex
864
+ isClickable = true
865
+ }
866
+ }
867
+
868
+ private fun processPendingCircles() {
869
+ if (googleMap == null) return
870
+ pendingCircleViews.forEach { addCircleViewToMap(it) }
871
+ pendingCircleViews.clear()
872
+ }
873
+
874
+ private fun addCircleViewToMap(circleView: LuggCircleView) {
875
+ val map = googleMap ?: return
876
+
877
+ val options = CircleOptions()
878
+ .center(circleView.center)
879
+ .radius(circleView.radius)
880
+ .fillColor(circleView.fillColor)
881
+ .strokeColor(circleView.strokeColor)
882
+ .strokeWidth(circleView.strokeWidth.dpToPx())
883
+ .zIndex(circleView.zIndex)
884
+ .clickable(true)
885
+
886
+ val circle = map.addCircle(options)
887
+ circleView.circle = circle
888
+ circleToViewMap[circle] = circleView
889
+ }
890
+
891
+ // endregion
892
+
893
+ // region Ground Overlay Management
894
+
895
+ override fun addGroundOverlayView(groundOverlayView: LuggGroundOverlayView) {
896
+ groundOverlayView.delegate = this
897
+ syncGroundOverlayView(groundOverlayView)
898
+ }
899
+
900
+ override fun removeGroundOverlayView(groundOverlayView: LuggGroundOverlayView) {
901
+ groundOverlayView.delegate = null
902
+ groundOverlayView.groundOverlay?.let { groundOverlayToViewMap.remove(it) }
903
+ groundOverlayView.groundOverlay?.remove()
904
+ groundOverlayView.groundOverlay = null
905
+ }
906
+
907
+ private fun syncGroundOverlayView(groundOverlayView: LuggGroundOverlayView) {
908
+ if (googleMap == null) {
909
+ pendingGroundOverlayViews.add(groundOverlayView)
910
+ return
911
+ }
912
+
913
+ val imageUri = groundOverlayView.imageUri
914
+ if (imageUri.isEmpty()) return
915
+
916
+ // Remove old overlay
917
+ groundOverlayView.groundOverlay?.let { groundOverlayToViewMap.remove(it) }
918
+ groundOverlayView.groundOverlay?.remove()
919
+ groundOverlayView.groundOverlay = null
920
+
921
+ // Load image async and add overlay
922
+ Thread {
923
+ try {
924
+ val connection = URL(imageUri).openConnection() as java.net.HttpURLConnection
925
+ connection.instanceFollowRedirects = true
926
+ connection.connect()
927
+ val bitmap = android.graphics.BitmapFactory.decodeStream(connection.inputStream)
928
+ connection.disconnect()
929
+ if (bitmap != null) {
930
+ mapView?.post {
931
+ addGroundOverlayToMap(groundOverlayView, bitmap)
932
+ }
933
+ }
934
+ } catch (_: Exception) {}
935
+ }.start()
936
+ }
937
+
938
+ private fun addGroundOverlayToMap(groundOverlayView: LuggGroundOverlayView, bitmap: android.graphics.Bitmap) {
939
+ val map = googleMap ?: return
940
+
941
+ val bounds = LatLngBounds(groundOverlayView.southwest, groundOverlayView.northeast)
942
+ val options = GroundOverlayOptions()
943
+ .image(BitmapDescriptorFactory.fromBitmap(bitmap))
944
+ .positionFromBounds(bounds)
945
+ .transparency(1f - groundOverlayView.overlayOpacity)
946
+ .bearing(groundOverlayView.bearing)
947
+ .zIndex(groundOverlayView.zIndex)
948
+ .clickable(groundOverlayView.tappable)
949
+
950
+ val overlay = map.addGroundOverlay(options)
951
+ if (overlay != null) {
952
+ groundOverlayView.groundOverlay = overlay
953
+ groundOverlayToViewMap[overlay] = groundOverlayView
954
+ }
955
+ }
956
+
957
+ private fun processPendingGroundOverlays() {
958
+ if (googleMap == null) return
959
+ pendingGroundOverlayViews.forEach { syncGroundOverlayView(it) }
960
+ pendingGroundOverlayViews.clear()
961
+ }
962
+
963
+ // endregion
964
+
965
+ // region Tile Overlay Management
966
+
967
+ override fun addTileOverlayView(tileOverlayView: LuggTileOverlayView) {
968
+ tileOverlayView.delegate = this
969
+ syncTileOverlayView(tileOverlayView)
970
+ }
971
+
972
+ override fun removeTileOverlayView(tileOverlayView: LuggTileOverlayView) {
973
+ tileOverlayView.delegate = null
974
+ tileOverlayView.tileOverlay?.remove()
975
+ tileOverlayView.tileOverlay = null
976
+ }
977
+
978
+ private fun syncTileOverlayView(tileOverlayView: LuggTileOverlayView) {
979
+ if (googleMap == null) {
980
+ pendingTileOverlayViews.add(tileOverlayView)
981
+ return
982
+ }
983
+
984
+ val urlTemplate = tileOverlayView.urlTemplate
985
+ if (urlTemplate.isEmpty()) return
986
+
987
+ // Remove old overlay
988
+ tileOverlayView.tileOverlay?.remove()
989
+ tileOverlayView.tileOverlay = null
990
+
991
+ val tileSize = tileOverlayView.tileSize
992
+ val hasBounds = tileOverlayView.hasBounds
993
+ val swLat = tileOverlayView.boundsSwLat
994
+ val swLng = tileOverlayView.boundsSwLng
995
+ val neLat = tileOverlayView.boundsNeLat
996
+ val neLng = tileOverlayView.boundsNeLng
997
+
998
+ val tileProvider = object : UrlTileProvider(tileSize, tileSize) {
999
+ override fun getTileUrl(x: Int, y: Int, zoom: Int): URL? {
1000
+ if (hasBounds) {
1001
+ val n = Math.pow(2.0, zoom.toDouble())
1002
+ val tileSWLat = Math.toDegrees(Math.atan(Math.sinh(Math.PI * (1 - 2.0 * (y + 1) / n))))
1003
+ val tileNELat = Math.toDegrees(Math.atan(Math.sinh(Math.PI * (1 - 2.0 * y / n))))
1004
+ val tileSWLng = x / n * 360.0 - 180.0
1005
+ val tileNELng = (x + 1) / n * 360.0 - 180.0
1006
+
1007
+ if (tileNELat < swLat ||
1008
+ tileSWLat > neLat ||
1009
+ tileNELng < swLng ||
1010
+ tileSWLng > neLng
1011
+ ) {
1012
+ return null
1013
+ }
1014
+ }
1015
+
1016
+ val url = urlTemplate
1017
+ .replace("{x}", x.toString())
1018
+ .replace("{y}", y.toString())
1019
+ .replace("{z}", zoom.toString())
1020
+ return try {
1021
+ URL(url)
1022
+ } catch (_: Exception) {
1023
+ null
1024
+ }
1025
+ }
1026
+ }
1027
+
1028
+ val options = TileOverlayOptions()
1029
+ .tileProvider(tileProvider)
1030
+ .transparency(1f - tileOverlayView.overlayOpacity)
1031
+ .zIndex(tileOverlayView.zIndex)
1032
+
1033
+ val overlay = googleMap?.addTileOverlay(options)
1034
+ tileOverlayView.tileOverlay = overlay
1035
+ }
1036
+
1037
+ private fun processPendingTileOverlays() {
1038
+ if (googleMap == null) return
1039
+ pendingTileOverlayViews.forEach { syncTileOverlayView(it) }
1040
+ pendingTileOverlayViews.clear()
1041
+ }
1042
+
1043
+ // endregion
1044
+
756
1045
  // region Lifecycle
757
1046
 
758
1047
  override fun pauseAnimations() {
@@ -1,9 +1,12 @@
1
1
  package com.luggmaps.core
2
2
 
3
3
  import android.view.View
4
+ import com.luggmaps.LuggCircleView
5
+ import com.luggmaps.LuggGroundOverlayView
4
6
  import com.luggmaps.LuggMarkerView
5
7
  import com.luggmaps.LuggPolygonView
6
8
  import com.luggmaps.LuggPolylineView
9
+ import com.luggmaps.LuggTileOverlayView
7
10
 
8
11
  data class EdgeInsets(val top: Int = 0, val left: Int = 0, val bottom: Int = 0, val right: Int = 0)
9
12
 
@@ -42,6 +45,12 @@ interface MapProvider {
42
45
  fun removePolylineView(polylineView: LuggPolylineView)
43
46
  fun addPolygonView(polygonView: LuggPolygonView)
44
47
  fun removePolygonView(polygonView: LuggPolygonView)
48
+ fun addCircleView(circleView: LuggCircleView)
49
+ fun removeCircleView(circleView: LuggCircleView)
50
+ fun addGroundOverlayView(groundOverlayView: LuggGroundOverlayView)
51
+ fun removeGroundOverlayView(groundOverlayView: LuggGroundOverlayView)
52
+ fun addTileOverlayView(tileOverlayView: LuggTileOverlayView)
53
+ fun removeTileOverlayView(tileOverlayView: LuggTileOverlayView)
45
54
 
46
55
  // Lifecycle
47
56
  fun pauseAnimations()
@@ -0,0 +1,12 @@
1
+ package com.luggmaps.events
2
+
3
+ import android.view.View
4
+ import com.facebook.react.bridge.Arguments
5
+ import com.facebook.react.uimanager.UIManagerHelper
6
+ import com.facebook.react.uimanager.events.Event
7
+
8
+ class CirclePressEvent(view: View) : Event<CirclePressEvent>(UIManagerHelper.getSurfaceId(view), view.id) {
9
+ override fun getEventName() = "topCirclePress"
10
+
11
+ override fun getEventData() = Arguments.createMap()
12
+ }
@@ -0,0 +1,12 @@
1
+ package com.luggmaps.events
2
+
3
+ import android.view.View
4
+ import com.facebook.react.bridge.Arguments
5
+ import com.facebook.react.uimanager.UIManagerHelper
6
+ import com.facebook.react.uimanager.events.Event
7
+
8
+ class GroundOverlayPressEvent(view: View) : Event<GroundOverlayPressEvent>(UIManagerHelper.getSurfaceId(view), view.id) {
9
+ override fun getEventName() = "topGroundOverlayPress"
10
+
11
+ override fun getEventData() = Arguments.createMap()
12
+ }
@@ -0,0 +1,12 @@
1
+ package com.luggmaps.events
2
+
3
+ import android.view.View
4
+ import com.facebook.react.bridge.Arguments
5
+ import com.facebook.react.uimanager.UIManagerHelper
6
+ import com.facebook.react.uimanager.events.Event
7
+
8
+ class TileOverlayPressEvent(view: View) : Event<TileOverlayPressEvent>(UIManagerHelper.getSurfaceId(view), view.id) {
9
+ override fun getEventName() = "topTileOverlayPress"
10
+
11
+ override fun getEventData() = Arguments.createMap()
12
+ }
@@ -0,0 +1,31 @@
1
+ #import <CoreLocation/CoreLocation.h>
2
+ #import <React/RCTViewComponentView.h>
3
+ #import <UIKit/UIKit.h>
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ @class LuggCircleView;
8
+
9
+ @protocol LuggCircleViewDelegate <NSObject>
10
+ @optional
11
+ - (void)circleViewDidUpdate:(LuggCircleView *)circleView;
12
+ @end
13
+
14
+ @interface LuggCircleView : RCTViewComponentView
15
+
16
+ @property(nonatomic, readonly) CLLocationCoordinate2D center;
17
+ @property(nonatomic, readonly) CLLocationDistance radius;
18
+ @property(nonatomic, readonly) UIColor *strokeColor;
19
+ @property(nonatomic, readonly) UIColor *fillColor;
20
+ @property(nonatomic, readonly) CGFloat strokeWidth;
21
+ @property(nonatomic, readonly) NSInteger zIndex;
22
+ @property(nonatomic, readonly) BOOL tappable;
23
+ @property(nonatomic, weak, nullable) id<LuggCircleViewDelegate> delegate;
24
+ @property(nonatomic, strong, nullable) NSObject *circle;
25
+ @property(nonatomic, weak, nullable) NSObject *renderer;
26
+
27
+ - (void)emitPressEvent;
28
+
29
+ @end
30
+
31
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,133 @@
1
+ #import "LuggCircleView.h"
2
+ #import "events/CirclePressEvent.h"
3
+
4
+ #import <react/renderer/components/RNMapsSpec/ComponentDescriptors.h>
5
+ #import <react/renderer/components/RNMapsSpec/EventEmitters.h>
6
+ #import <react/renderer/components/RNMapsSpec/Props.h>
7
+ #import <react/renderer/components/RNMapsSpec/RCTComponentViewHelpers.h>
8
+
9
+ #import "RCTFabricComponentsPlugins.h"
10
+ #import <React/RCTConversions.h>
11
+
12
+ using namespace facebook::react;
13
+ using namespace luggmaps::events;
14
+
15
+ @interface LuggCircleView () <RCTLuggCircleViewViewProtocol>
16
+ @end
17
+
18
+ @implementation LuggCircleView {
19
+ CLLocationCoordinate2D _center;
20
+ CLLocationDistance _radius;
21
+ UIColor *_strokeColor;
22
+ UIColor *_fillColor;
23
+ CGFloat _strokeWidth;
24
+ NSInteger _zIndex;
25
+ BOOL _tappable;
26
+ }
27
+
28
+ + (ComponentDescriptorProvider)componentDescriptorProvider {
29
+ return concreteComponentDescriptorProvider<
30
+ LuggCircleViewComponentDescriptor>();
31
+ }
32
+
33
+ - (instancetype)initWithFrame:(CGRect)frame {
34
+ if (self = [super initWithFrame:frame]) {
35
+ static const auto defaultProps =
36
+ std::make_shared<const LuggCircleViewProps>();
37
+ _props = defaultProps;
38
+
39
+ _center = CLLocationCoordinate2DMake(0, 0);
40
+ _radius = 0;
41
+ _strokeColor = [UIColor blackColor];
42
+ _fillColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3];
43
+ _strokeWidth = 1.0;
44
+
45
+ self.hidden = YES;
46
+ }
47
+
48
+ return self;
49
+ }
50
+
51
+ - (void)updateProps:(Props::Shared const &)props
52
+ oldProps:(Props::Shared const &)oldProps {
53
+ [super updateProps:props oldProps:oldProps];
54
+ const auto &newViewProps =
55
+ *std::static_pointer_cast<LuggCircleViewProps const>(props);
56
+
57
+ _center = CLLocationCoordinate2DMake(newViewProps.center.latitude,
58
+ newViewProps.center.longitude);
59
+ _radius = newViewProps.radius;
60
+
61
+ if (newViewProps.strokeColor) {
62
+ UIColor *color = RCTUIColorFromSharedColor(newViewProps.strokeColor);
63
+ if (color) {
64
+ _strokeColor = color;
65
+ }
66
+ }
67
+
68
+ if (newViewProps.fillColor) {
69
+ UIColor *color = RCTUIColorFromSharedColor(newViewProps.fillColor);
70
+ if (color) {
71
+ _fillColor = color;
72
+ }
73
+ }
74
+
75
+ _strokeWidth = newViewProps.strokeWidth > 0 ? newViewProps.strokeWidth : 1.0;
76
+ _zIndex = newViewProps.zIndex.value_or(0);
77
+ _tappable = newViewProps.tappable;
78
+ }
79
+
80
+ - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
81
+ [super finalizeUpdates:updateMask];
82
+
83
+ if (updateMask & RNComponentViewUpdateMaskProps) {
84
+ if ([self.delegate respondsToSelector:@selector(circleViewDidUpdate:)]) {
85
+ [self.delegate circleViewDidUpdate:self];
86
+ }
87
+ }
88
+ }
89
+
90
+ - (CLLocationCoordinate2D)center {
91
+ return _center;
92
+ }
93
+
94
+ - (CLLocationDistance)radius {
95
+ return _radius;
96
+ }
97
+
98
+ - (UIColor *)strokeColor {
99
+ return _strokeColor;
100
+ }
101
+
102
+ - (UIColor *)fillColor {
103
+ return _fillColor;
104
+ }
105
+
106
+ - (CGFloat)strokeWidth {
107
+ return _strokeWidth;
108
+ }
109
+
110
+ - (NSInteger)zIndex {
111
+ return _zIndex;
112
+ }
113
+
114
+ - (BOOL)tappable {
115
+ return _tappable;
116
+ }
117
+
118
+ - (void)emitPressEvent {
119
+ CirclePressEvent::emit<LuggCircleViewEventEmitter>(_eventEmitter);
120
+ }
121
+
122
+ - (void)prepareForRecycle {
123
+ [super prepareForRecycle];
124
+ self.circle = nil;
125
+ self.renderer = nil;
126
+ self.delegate = nil;
127
+ }
128
+
129
+ Class<RCTComponentViewProtocol> LuggCircleViewCls(void) {
130
+ return LuggCircleView.class;
131
+ }
132
+
133
+ @end
@@ -0,0 +1,30 @@
1
+ #import <CoreLocation/CoreLocation.h>
2
+ #import <React/RCTViewComponentView.h>
3
+ #import <UIKit/UIKit.h>
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ @class LuggGroundOverlayView;
8
+
9
+ @protocol LuggGroundOverlayViewDelegate <NSObject>
10
+ @optional
11
+ - (void)groundOverlayViewDidUpdate:(LuggGroundOverlayView *)groundOverlayView;
12
+ @end
13
+
14
+ @interface LuggGroundOverlayView : RCTViewComponentView
15
+
16
+ @property(nonatomic, readonly) NSString *imageUri;
17
+ @property(nonatomic, readonly) CLLocationCoordinate2D northeast;
18
+ @property(nonatomic, readonly) CLLocationCoordinate2D southwest;
19
+ @property(nonatomic, readonly) CGFloat opacity;
20
+ @property(nonatomic, readonly) CGFloat bearing;
21
+ @property(nonatomic, readonly) NSInteger zIndex;
22
+ @property(nonatomic, readonly) BOOL tappable;
23
+ @property(nonatomic, weak, nullable) id<LuggGroundOverlayViewDelegate> delegate;
24
+ @property(nonatomic, strong, nullable) NSObject *overlay;
25
+
26
+ - (void)emitPressEvent;
27
+
28
+ @end
29
+
30
+ NS_ASSUME_NONNULL_END