react-native-google-maps-plus 1.7.0-dev.9 → 1.8.0

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 (71) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/gradle.properties +2 -1
  3. package/android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt +120 -124
  4. package/android/src/main/java/com/rngooglemapsplus/MapCircleBuilder.kt +2 -3
  5. package/android/src/main/java/com/rngooglemapsplus/MapMarkerBuilder.kt +83 -53
  6. package/android/src/main/java/com/rngooglemapsplus/MapPolygonBuilder.kt +6 -23
  7. package/android/src/main/java/com/rngooglemapsplus/MapPolylineBuilder.kt.kt +12 -39
  8. package/android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt +30 -12
  9. package/android/src/main/java/com/rngooglemapsplus/extensions/BitmapExtension.kt +35 -0
  10. package/android/src/main/java/com/rngooglemapsplus/extensions/LatLngBoundsExtension.kt +31 -0
  11. package/android/src/main/java/com/rngooglemapsplus/extensions/MapObjectTagExtensions.kt +84 -0
  12. package/android/src/main/java/com/rngooglemapsplus/extensions/RNLineCapTypeExtension.kt +14 -0
  13. package/android/src/main/java/com/rngooglemapsplus/extensions/RNLineJoinTypeExtension.kt +12 -0
  14. package/android/src/main/java/com/rngooglemapsplus/extensions/RNMapCircleExtension.kt +7 -1
  15. package/android/src/main/java/com/rngooglemapsplus/extensions/RNMarkerExtension.kt +54 -17
  16. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolygonExtension.kt +31 -1
  17. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolylineExtension.kt +6 -1
  18. package/ios/GoogleMapViewImpl.swift +81 -64
  19. package/ios/MapCircleBuilder.swift +2 -3
  20. package/ios/MapMarkerBuilder.swift +106 -50
  21. package/ios/MapPolygonBuilder.swift +6 -41
  22. package/ios/MapPolylineBuilder.swift +2 -10
  23. package/ios/RNGoogleMapsPlusView.swift +24 -11
  24. package/ios/extensions/MapObjectTag+Extension.swift +93 -0
  25. package/ios/extensions/RNCircle+Extension.swift +14 -5
  26. package/ios/extensions/RNLatLng+Extension.swift +11 -0
  27. package/ios/extensions/RNLineCapType+Extension.swift +10 -0
  28. package/ios/extensions/RNLineJoinType+Extension.swift +11 -0
  29. package/ios/extensions/RNMarker+Extension.swift +43 -12
  30. package/ios/extensions/RNPolygon+Extension.swift.swift +50 -21
  31. package/ios/extensions/RNPolyline+Extension.swift.swift +15 -26
  32. package/ios/extensions/UIImage+Extension.swift +45 -0
  33. package/lib/module/types.js.map +1 -1
  34. package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts +12 -10
  35. package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts.map +1 -1
  36. package/lib/typescript/src/types.d.ts +2 -1
  37. package/lib/typescript/src/types.d.ts.map +1 -1
  38. package/nitrogen/generated/android/RNGoogleMapsPlusOnLoad.cpp +4 -4
  39. package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +75 -0
  40. package/nitrogen/generated/android/c++/JFunc_void_std__string_RNLatLng.hpp +77 -0
  41. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +100 -92
  42. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.hpp +22 -20
  43. package/nitrogen/generated/android/c++/JRNInitialProps.hpp +7 -3
  44. package/nitrogen/generated/android/c++/JRNMarker.hpp +7 -7
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/{Func_void_std__optional_std__string_.kt → Func_void_std__string.kt} +12 -12
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/{Func_void_std__optional_std__string__RNLatLng.kt → Func_void_std__string_RNLatLng.kt} +12 -12
  47. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/HybridRNGoogleMapsPlusViewSpec.kt +38 -30
  48. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNInitialProps.kt +6 -3
  49. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMarker.kt +6 -6
  50. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.cpp +16 -8
  51. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +58 -36
  52. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +32 -20
  53. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +6 -6
  54. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +47 -0
  55. package/nitrogen/generated/ios/swift/Func_void_std__string_RNLatLng.swift +47 -0
  56. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec.swift +12 -10
  57. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec_cxx.swift +142 -180
  58. package/nitrogen/generated/ios/swift/RNInitialProps.swift +31 -1
  59. package/nitrogen/generated/ios/swift/RNMarker.swift +24 -31
  60. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.cpp +2 -0
  61. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.hpp +22 -20
  62. package/nitrogen/generated/shared/c++/RNInitialProps.hpp +6 -2
  63. package/nitrogen/generated/shared/c++/RNMarker.hpp +6 -6
  64. package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.cpp +20 -20
  65. package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.hpp +10 -10
  66. package/package.json +1 -1
  67. package/src/RNGoogleMapsPlusView.nitro.ts +14 -10
  68. package/src/types.ts +2 -1
  69. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__string_.hpp +0 -76
  70. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__string__RNLatLng.hpp +0 -78
  71. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string__RNLatLng.swift +0 -54
@@ -1,11 +1,15 @@
1
1
  package com.rngooglemapsplus
2
2
 
3
+ import MarkerTag
3
4
  import android.graphics.Bitmap
4
5
  import android.graphics.BitmapFactory
5
6
  import android.graphics.Canvas
6
7
  import android.graphics.Typeface
8
+ import android.graphics.drawable.PictureDrawable
7
9
  import android.util.Base64
8
10
  import android.util.LruCache
11
+ import android.widget.ImageView
12
+ import android.widget.LinearLayout
9
13
  import androidx.core.graphics.createBitmap
10
14
  import com.caverock.androidsvg.SVG
11
15
  import com.caverock.androidsvg.SVGExternalFileResolver
@@ -15,6 +19,10 @@ import com.google.android.gms.maps.model.BitmapDescriptor
15
19
  import com.google.android.gms.maps.model.BitmapDescriptorFactory
16
20
  import com.google.android.gms.maps.model.Marker
17
21
  import com.google.android.gms.maps.model.MarkerOptions
22
+ import com.rngooglemapsplus.extensions.anchorEquals
23
+ import com.rngooglemapsplus.extensions.coordinatesEquals
24
+ import com.rngooglemapsplus.extensions.infoWindowAnchorEquals
25
+ import com.rngooglemapsplus.extensions.markerInfoWindowStyleEquals
18
26
  import com.rngooglemapsplus.extensions.markerStyleEquals
19
27
  import com.rngooglemapsplus.extensions.onUi
20
28
  import com.rngooglemapsplus.extensions.styleHash
@@ -69,7 +77,10 @@ class MapMarkerBuilder(
69
77
  val height = (svg.documentHeight.takeIf { it > 0 } ?: 128f).toInt()
70
78
 
71
79
  createBitmap(width, height).apply {
72
- Canvas(this).also(svg::renderToCanvas)
80
+ density = context.resources.displayMetrics.densityDpi
81
+ Canvas(this).also {
82
+ svg.renderToCanvas(it)
83
+ }
73
84
  }
74
85
  }
75
86
 
@@ -90,10 +101,12 @@ class MapMarkerBuilder(
90
101
  val innerSvg = SVG.getFromString(svgText)
91
102
  val w = innerSvg.documentWidth.takeIf { it > 0 } ?: 128f
92
103
  val h = innerSvg.documentHeight.takeIf { it > 0 } ?: 128f
93
- val bmp = createBitmap(w.toInt(), h.toInt())
94
- val canvas = Canvas(bmp)
95
- innerSvg.renderToCanvas(canvas)
96
- bmp
104
+ createBitmap(w.toInt(), h.toInt()).apply {
105
+ density = context.resources.displayMetrics.densityDpi
106
+ Canvas(this).also {
107
+ innerSvg.renderToCanvas(it)
108
+ }
109
+ }
97
110
  } else {
98
111
  conn.inputStream.use { BitmapFactory.decodeStream(it) }
99
112
  }
@@ -165,51 +178,39 @@ class MapMarkerBuilder(
165
178
  next: RNMarker,
166
179
  marker: Marker,
167
180
  ) = onUi {
168
- if (prev.coordinate.latitude != next.coordinate.latitude ||
169
- prev.coordinate.longitude != next.coordinate.longitude
170
- ) {
181
+ if (!prev.coordinatesEquals(next)) {
171
182
  marker.position = next.coordinate.toLatLng()
172
183
  }
173
184
 
174
185
  if (!prev.markerStyleEquals(next)) {
175
- buildIconAsync(marker.id, next) { icon ->
186
+ buildIconAsync(next) { icon ->
176
187
  marker.setIcon(icon)
177
- if (prev.infoWindowAnchor?.x != next.infoWindowAnchor?.x ||
178
- prev.infoWindowAnchor?.y != next.infoWindowAnchor?.y
179
- ) {
180
- marker.setInfoWindowAnchor(
181
- (next.infoWindowAnchor?.x ?: 0.5f).toFloat(),
182
- (next.infoWindowAnchor?.y ?: 0f).toFloat(),
183
- )
184
- }
185
-
186
- if (prev.anchor?.x != next.anchor?.x ||
187
- prev.anchor?.y != next.anchor?.y
188
- ) {
188
+ if (!prev.anchorEquals(next)) {
189
189
  marker.setAnchor(
190
190
  (next.anchor?.x ?: 0.5f).toFloat(),
191
191
  (next.anchor?.y ?: 1.0f).toFloat(),
192
192
  )
193
193
  }
194
+ if (!prev.infoWindowAnchorEquals(next)) {
195
+ marker.setInfoWindowAnchor(
196
+ (next.infoWindowAnchor?.x ?: 0.5f).toFloat(),
197
+ (next.infoWindowAnchor?.y ?: 0f).toFloat(),
198
+ )
199
+ }
194
200
  }
195
201
  } else {
196
- if (prev.infoWindowAnchor?.x != next.infoWindowAnchor?.x ||
197
- prev.infoWindowAnchor?.y != next.infoWindowAnchor?.y
198
- ) {
199
- marker.setInfoWindowAnchor(
200
- (next.infoWindowAnchor?.x ?: 0.5f).toFloat(),
201
- (next.infoWindowAnchor?.y ?: 0f).toFloat(),
202
- )
203
- }
204
-
205
- if (prev.anchor?.x != next.anchor?.x ||
206
- prev.anchor?.y != next.anchor?.y
207
- ) {
202
+ if (!prev.anchorEquals(next)) {
208
203
  marker.setAnchor(
209
204
  (next.anchor?.x ?: 0.5f).toFloat(),
210
205
  (next.anchor?.y ?: 1.0f).toFloat(),
211
206
  )
212
207
  }
208
+ if (!prev.infoWindowAnchorEquals(next)) {
209
+ marker.setInfoWindowAnchor(
210
+ (next.infoWindowAnchor?.x ?: 0.5f).toFloat(),
211
+ (next.infoWindowAnchor?.y ?: 0f).toFloat(),
212
+ )
213
+ }
213
214
  }
214
215
 
215
216
  if (prev.title != next.title) {
@@ -239,14 +240,17 @@ class MapMarkerBuilder(
239
240
  if (prev.zIndex != next.zIndex) {
240
241
  marker.zIndex = next.zIndex?.toFloat() ?: 0f
241
242
  }
243
+
244
+ if (!prev.markerInfoWindowStyleEquals(next)) {
245
+ marker.tag = MarkerTag(id = next.id, iconSvg = next.infoWindowIconSvg)
246
+ }
242
247
  }
243
248
 
244
249
  fun buildIconAsync(
245
- id: String,
246
250
  m: RNMarker,
247
251
  onReady: (BitmapDescriptor?) -> Unit,
248
252
  ) {
249
- jobsById[id]?.cancel()
253
+ jobsById[m.id]?.cancel()
250
254
 
251
255
  m.iconSvg ?: return onReady(null)
252
256
 
@@ -275,11 +279,11 @@ class MapMarkerBuilder(
275
279
  iconCache.evictAll()
276
280
  } catch (_: Throwable) {
277
281
  } finally {
278
- jobsById.remove(id)
282
+ jobsById.remove(m.id)
279
283
  }
280
284
  }
281
285
 
282
- jobsById[id] = job
286
+ jobsById[m.id] = job
283
287
  }
284
288
 
285
289
  fun cancelIconJob(id: String) {
@@ -296,6 +300,31 @@ class MapMarkerBuilder(
296
300
  iconCache.evictAll()
297
301
  }
298
302
 
303
+ fun buildInfoWindow(iconSvg: RNMarkerSvg?): ImageView? {
304
+ val iconSvg = iconSvg ?: return null
305
+
306
+ val svgView =
307
+ ImageView(context).apply {
308
+ layoutParams =
309
+ LinearLayout.LayoutParams(
310
+ iconSvg.width.dpToPx().toInt(),
311
+ iconSvg.height.dpToPx().toInt(),
312
+ )
313
+ }
314
+
315
+ try {
316
+ val svg = SVG.getFromString(iconSvg.svgString)
317
+ svg.setDocumentWidth(iconSvg.width.dpToPx())
318
+ svg.setDocumentHeight(iconSvg.height.dpToPx())
319
+ val drawable = PictureDrawable(svg.renderToPicture())
320
+ svgView.setImageDrawable(drawable)
321
+ } catch (e: Exception) {
322
+ return null
323
+ }
324
+
325
+ return svgView
326
+ }
327
+
299
328
  private suspend fun renderBitmap(m: RNMarker): Bitmap? {
300
329
  m.iconSvg ?: return null
301
330
 
@@ -304,27 +333,28 @@ class MapMarkerBuilder(
304
333
  coroutineContext.ensureActive()
305
334
  val svg = SVG.getFromString(m.iconSvg.svgString)
306
335
 
307
- coroutineContext.ensureActive()
308
- svg.setDocumentWidth(m.iconSvg.width.dpToPx())
309
- svg.setDocumentHeight(m.iconSvg.height.dpToPx())
336
+ val wPx =
337
+ m.iconSvg.width
338
+ .dpToPx()
339
+ .toInt()
340
+ val hPx =
341
+ m.iconSvg.height
342
+ .dpToPx()
343
+ .toInt()
310
344
 
311
345
  coroutineContext.ensureActive()
312
- bmp =
313
- createBitmap(
314
- m.iconSvg.width
315
- .dpToPx()
316
- .toInt(),
317
- m.iconSvg.height
318
- .dpToPx()
319
- .toInt(),
320
- Bitmap.Config.ARGB_8888,
321
- )
346
+ svg.setDocumentWidth(wPx.toFloat())
347
+ svg.setDocumentHeight(hPx.toFloat())
322
348
 
323
349
  coroutineContext.ensureActive()
324
- val canvas = Canvas(bmp)
325
- svg.renderToCanvas(canvas)
350
+ bmp =
351
+ createBitmap(wPx, hPx, Bitmap.Config.ARGB_8888).apply {
352
+ density = context.resources.displayMetrics.densityDpi
353
+ Canvas(this).also {
354
+ svg.renderToCanvas(it)
355
+ }
356
+ }
326
357
 
327
- coroutineContext.ensureActive()
328
358
  return bmp
329
359
  } catch (t: Throwable) {
330
360
  try {
@@ -4,9 +4,12 @@ import android.graphics.Color
4
4
  import com.facebook.react.uimanager.PixelUtil.dpToPx
5
5
  import com.google.android.gms.maps.model.Polygon
6
6
  import com.google.android.gms.maps.model.PolygonOptions
7
+ import com.rngooglemapsplus.extensions.coordinatesEquals
8
+ import com.rngooglemapsplus.extensions.holesEquals
7
9
  import com.rngooglemapsplus.extensions.onUi
8
10
  import com.rngooglemapsplus.extensions.toColor
9
11
  import com.rngooglemapsplus.extensions.toLatLng
12
+ import com.rngooglemapsplus.extensions.toMapsPolygonHoles
10
13
 
11
14
  class MapPolygonBuilder {
12
15
  fun build(poly: RNPolygon): PolygonOptions =
@@ -32,32 +35,12 @@ class MapPolygonBuilder {
32
35
  next: RNPolygon,
33
36
  poly: Polygon,
34
37
  ) = onUi {
35
- val coordsChanged =
36
- prev.coordinates.size != next.coordinates.size ||
37
- !prev.coordinates.zip(next.coordinates).all { (a, b) ->
38
- a.latitude == b.latitude && a.longitude == b.longitude
39
- }
40
-
41
- if (coordsChanged) {
38
+ if (!prev.coordinatesEquals(next)) {
42
39
  poly.points = next.coordinates.map { it.toLatLng() }
43
40
  }
44
41
 
45
- val prevHoles = prev.holes?.toList() ?: emptyList()
46
- val nextHoles = next.holes?.toList() ?: emptyList()
47
- val holesChanged =
48
- prevHoles.size != nextHoles.size ||
49
- !prevHoles.zip(nextHoles).all { (ha, hb) ->
50
- ha.coordinates.size == hb.coordinates.size &&
51
- ha.coordinates.zip(hb.coordinates).all { (a, b) ->
52
- a.latitude == b.latitude && a.longitude == b.longitude
53
- }
54
- }
55
-
56
- if (holesChanged) {
57
- poly.holes =
58
- nextHoles.map { hole ->
59
- hole.coordinates.map { it.toLatLng() }
60
- }
42
+ if (!prev.holesEquals(next)) {
43
+ poly.holes = next.holes?.toMapsPolygonHoles() ?: emptyList()
61
44
  }
62
45
 
63
46
  if (prev.fillColor != next.fillColor) {
@@ -2,16 +2,14 @@ package com.rngooglemapsplus
2
2
 
3
3
  import android.graphics.Color
4
4
  import com.facebook.react.uimanager.PixelUtil.dpToPx
5
- import com.google.android.gms.maps.model.ButtCap
6
- import com.google.android.gms.maps.model.Cap
7
- import com.google.android.gms.maps.model.JointType
8
5
  import com.google.android.gms.maps.model.Polyline
9
6
  import com.google.android.gms.maps.model.PolylineOptions
10
- import com.google.android.gms.maps.model.RoundCap
11
- import com.google.android.gms.maps.model.SquareCap
7
+ import com.rngooglemapsplus.extensions.coordinatesEquals
12
8
  import com.rngooglemapsplus.extensions.onUi
13
9
  import com.rngooglemapsplus.extensions.toColor
14
10
  import com.rngooglemapsplus.extensions.toLatLng
11
+ import com.rngooglemapsplus.extensions.toMapJointType
12
+ import com.rngooglemapsplus.extensions.toMapLineCap
15
13
 
16
14
  class MapPolylineBuilder {
17
15
  fun build(pl: RNPolyline): PolylineOptions =
@@ -21,10 +19,10 @@ class MapPolylineBuilder {
21
19
  }
22
20
  pl.width?.let { width(it.dpToPx()) }
23
21
  pl.lineCap?.let {
24
- startCap(mapLineCap(it))
25
- endCap(mapLineCap(it))
22
+ startCap(it.toMapLineCap())
23
+ endCap(it.toMapLineCap())
26
24
  }
27
- pl.lineJoin?.let { jointType(mapLineJoin(it)) }
25
+ pl.lineJoin?.let { jointType(it.toMapJointType()) }
28
26
  pl.color?.let { color(it.toColor()) }
29
27
  pl.geodesic?.let { geodesic(it) }
30
28
  pl.pressable?.let { clickable(it) }
@@ -36,13 +34,7 @@ class MapPolylineBuilder {
36
34
  next: RNPolyline,
37
35
  polyline: Polyline,
38
36
  ) = onUi {
39
- val coordsChanged =
40
- prev.coordinates.size != next.coordinates.size ||
41
- !prev.coordinates.zip(next.coordinates).all { (a, b) ->
42
- a.latitude == b.latitude && a.longitude == b.longitude
43
- }
44
-
45
- if (coordsChanged) {
37
+ if (!prev.coordinatesEquals(next)) {
46
38
  polyline.points = next.coordinates.map { it.toLatLng() }
47
39
  }
48
40
 
@@ -50,17 +42,13 @@ class MapPolylineBuilder {
50
42
  polyline.width = next.width?.dpToPx() ?: 1f
51
43
  }
52
44
 
53
- val newCap = mapLineCap(next.lineCap ?: RNLineCapType.BUTT)
54
- val prevCap = mapLineCap(prev.lineCap ?: RNLineCapType.BUTT)
55
- if (newCap != prevCap) {
56
- polyline.startCap = newCap
57
- polyline.endCap = newCap
45
+ if (prev.lineCap != next.lineCap) {
46
+ polyline.startCap = next.lineCap.toMapLineCap()
47
+ polyline.endCap = next.lineCap.toMapLineCap()
58
48
  }
59
49
 
60
- val newJoin = mapLineJoin(next.lineJoin ?: RNLineJoinType.MITER)
61
- val prevJoin = mapLineJoin(prev.lineJoin ?: RNLineJoinType.MITER)
62
- if (newJoin != prevJoin) {
63
- polyline.jointType = newJoin
50
+ if (prev.lineJoin != next.lineJoin) {
51
+ polyline.jointType = next.lineJoin.toMapJointType()
64
52
  }
65
53
 
66
54
  if (prev.color != next.color) {
@@ -79,19 +67,4 @@ class MapPolylineBuilder {
79
67
  polyline.zIndex = next.zIndex?.toFloat() ?: 0f
80
68
  }
81
69
  }
82
-
83
- private fun mapLineCap(type: RNLineCapType?): Cap =
84
- when (type) {
85
- RNLineCapType.ROUND -> RoundCap()
86
- RNLineCapType.SQUARE -> SquareCap()
87
- else -> ButtCap()
88
- }
89
-
90
- private fun mapLineJoin(type: RNLineJoinType?): Int =
91
- when (type) {
92
- RNLineJoinType.ROUND -> JointType.ROUND
93
- RNLineJoinType.BEVEL -> JointType.BEVEL
94
- RNLineJoinType.MITER -> JointType.DEFAULT
95
- null -> JointType.DEFAULT
96
- }
97
70
  }
@@ -1,5 +1,6 @@
1
1
  package com.rngooglemapsplus
2
2
 
3
+ import MarkerTag
3
4
  import com.facebook.proguard.annotations.DoNotStrip
4
5
  import com.facebook.react.uimanager.ThemedReactContext
5
6
  import com.google.android.gms.maps.GoogleMapOptions
@@ -11,6 +12,7 @@ import com.rngooglemapsplus.extensions.markerEquals
11
12
  import com.rngooglemapsplus.extensions.polygonEquals
12
13
  import com.rngooglemapsplus.extensions.polylineEquals
13
14
  import com.rngooglemapsplus.extensions.toCameraPosition
15
+ import com.rngooglemapsplus.extensions.toColor
14
16
  import com.rngooglemapsplus.extensions.toCompressFormat
15
17
  import com.rngooglemapsplus.extensions.toFileExtension
16
18
  import com.rngooglemapsplus.extensions.toGoogleMapType
@@ -47,6 +49,7 @@ class RNGoogleMapsPlusView(
47
49
  initialProps?.mapId?.let { mapId(it) }
48
50
  initialProps?.liteMode?.let { liteMode(it) }
49
51
  initialProps?.camera?.let { camera(it.toCameraPosition(current = null)) }
52
+ initialProps?.backgroundColor?.let { backgroundColor(it.toColor()) }
50
53
  }
51
54
  view.initMapView(options)
52
55
  }
@@ -148,8 +151,15 @@ class RNGoogleMapsPlusView(
148
151
  val prev = prevById[id]
149
152
  when {
150
153
  prev == null ->
151
- markerBuilder.buildIconAsync(id, next) { icon ->
152
- view.addMarker(id, markerBuilder.build(next, icon))
154
+ markerBuilder.buildIconAsync(next) { icon ->
155
+ view.addMarker(
156
+ id,
157
+ markerBuilder.build(next, icon),
158
+ MarkerTag(
159
+ id = id,
160
+ iconSvg = next.infoWindowIconSvg,
161
+ ),
162
+ )
153
163
  }
154
164
 
155
165
  !prev.markerEquals(next) ->
@@ -320,7 +330,7 @@ class RNGoogleMapsPlusView(
320
330
  view.onMapLongPress = cb
321
331
  }
322
332
 
323
- override var onMarkerPress: ((String?) -> Unit)? = null
333
+ override var onMarkerPress: ((String) -> Unit)? = null
324
334
  set(cb) {
325
335
  view.onMarkerPress = cb
326
336
  }
@@ -330,32 +340,32 @@ class RNGoogleMapsPlusView(
330
340
  view.onPoiPress = cb
331
341
  }
332
342
 
333
- override var onPolylinePress: ((String?) -> Unit)? = null
343
+ override var onPolylinePress: ((String) -> Unit)? = null
334
344
  set(cb) {
335
345
  view.onPolylinePress = cb
336
346
  }
337
347
 
338
- override var onPolygonPress: ((String?) -> Unit)? = null
348
+ override var onPolygonPress: ((String) -> Unit)? = null
339
349
  set(cb) {
340
350
  view.onPolygonPress = cb
341
351
  }
342
352
 
343
- override var onCirclePress: ((String?) -> Unit)? = null
353
+ override var onCirclePress: ((String) -> Unit)? = null
344
354
  set(cb) {
345
355
  view.onCirclePress = cb
346
356
  }
347
357
 
348
- override var onMarkerDragStart: ((String?, RNLatLng) -> Unit)? = null
358
+ override var onMarkerDragStart: ((String, RNLatLng) -> Unit)? = null
349
359
  set(cb) {
350
360
  view.onMarkerDragStart = cb
351
361
  }
352
362
 
353
- override var onMarkerDrag: ((String?, RNLatLng) -> Unit)? = null
363
+ override var onMarkerDrag: ((String, RNLatLng) -> Unit)? = null
354
364
  set(cb) {
355
365
  view.onMarkerDrag = cb
356
366
  }
357
367
 
358
- override var onMarkerDragEnd: ((String?, RNLatLng) -> Unit)? = null
368
+ override var onMarkerDragEnd: ((String, RNLatLng) -> Unit)? = null
359
369
  set(cb) {
360
370
  view.onMarkerDragEnd = cb
361
371
  }
@@ -370,17 +380,17 @@ class RNGoogleMapsPlusView(
370
380
  view.onIndoorLevelActivated = cb
371
381
  }
372
382
 
373
- override var onInfoWindowPress: ((String?) -> Unit)? = null
383
+ override var onInfoWindowPress: ((String) -> Unit)? = null
374
384
  set(cb) {
375
385
  view.onInfoWindowPress = cb
376
386
  }
377
387
 
378
- override var onInfoWindowClose: ((String?) -> Unit)? = null
388
+ override var onInfoWindowClose: ((String) -> Unit)? = null
379
389
  set(cb) {
380
390
  view.onInfoWindowClose = cb
381
391
  }
382
392
 
383
- override var onInfoWindowLongPress: ((String?) -> Unit)? = null
393
+ override var onInfoWindowLongPress: ((String) -> Unit)? = null
384
394
  set(cb) {
385
395
  view.onInfoWindowLongPress = cb
386
396
  }
@@ -410,6 +420,14 @@ class RNGoogleMapsPlusView(
410
420
  view.onCameraChangeComplete = cb
411
421
  }
412
422
 
423
+ override fun showMarkerInfoWindow(id: String) {
424
+ view.showMarkerInfoWindow(id)
425
+ }
426
+
427
+ override fun hideMarkerInfoWindow(id: String) {
428
+ view.hideMarkerInfoWindow(id)
429
+ }
430
+
413
431
  override fun setCamera(
414
432
  camera: RNCamera,
415
433
  animated: Boolean?,
@@ -0,0 +1,35 @@
1
+ package com.rngooglemapsplus.extensions
2
+
3
+ import android.content.Context
4
+ import android.graphics.Bitmap
5
+ import android.util.Base64
6
+ import android.util.Size
7
+ import androidx.core.graphics.scale
8
+ import java.io.ByteArrayOutputStream
9
+ import java.io.File
10
+ import java.io.FileOutputStream
11
+
12
+ fun Bitmap.encode(
13
+ context: Context,
14
+ targetSize: Size?,
15
+ format: String,
16
+ compressFormat: Bitmap.CompressFormat,
17
+ quality: Double,
18
+ asFile: Boolean,
19
+ ): String? =
20
+ try {
21
+ targetSize?.let { scale(it.width, it.height) }
22
+ val output = ByteArrayOutputStream()
23
+ compress(compressFormat, (quality * 100).toInt().coerceIn(0, 100), output)
24
+ val bytes = output.toByteArray()
25
+
26
+ if (asFile) {
27
+ val file = File(context.cacheDir, "snapshot_${System.currentTimeMillis()}.$format")
28
+ FileOutputStream(file).use { it.write(bytes) }
29
+ file.absolutePath
30
+ } else {
31
+ "data:image/$format;base64," + Base64.encodeToString(bytes, Base64.NO_WRAP)
32
+ }
33
+ } catch (_: Exception) {
34
+ null
35
+ }
@@ -1,10 +1,41 @@
1
1
  package com.rngooglemapsplus.extensions
2
2
 
3
+ import com.facebook.react.uimanager.PixelUtil.dpToPx
4
+ import com.google.android.gms.maps.model.LatLng
3
5
  import com.google.android.gms.maps.model.LatLngBounds
4
6
  import com.rngooglemapsplus.RNLatLngBounds
7
+ import com.rngooglemapsplus.RNMapPadding
5
8
 
6
9
  fun LatLngBounds.toRnLatLngBounds(): RNLatLngBounds =
7
10
  RNLatLngBounds(
8
11
  northeast = northeast.toRnLatLng(),
9
12
  southwest = southwest.toRnLatLng(),
10
13
  )
14
+
15
+ fun LatLngBounds.withPaddingPixels(
16
+ mapWidthPx: Int,
17
+ mapHeightPx: Int,
18
+ padding: RNMapPadding,
19
+ ): LatLngBounds {
20
+ val latSpan = northeast.latitude - southwest.latitude
21
+ val lngSpan = northeast.longitude - southwest.longitude
22
+ if (latSpan == 0.0 && lngSpan == 0.0) return this
23
+
24
+ val latPerPixel = if (mapHeightPx != 0) latSpan / mapHeightPx else 0.0
25
+ val lngPerPixel = if (mapWidthPx != 0) lngSpan / mapWidthPx else 0.0
26
+
27
+ val builder = LatLngBounds.builder()
28
+ builder.include(
29
+ LatLng(
30
+ northeast.latitude + (padding.top.dpToPx() * latPerPixel),
31
+ northeast.longitude + (padding.right.dpToPx() * lngPerPixel),
32
+ ),
33
+ )
34
+ builder.include(
35
+ LatLng(
36
+ southwest.latitude - (padding.bottom.dpToPx() * latPerPixel),
37
+ southwest.longitude - (padding.left.dpToPx() * lngPerPixel),
38
+ ),
39
+ )
40
+ return builder.build()
41
+ }
@@ -0,0 +1,84 @@
1
+ import android.util.Log
2
+ import com.google.android.gms.maps.model.Circle
3
+ import com.google.android.gms.maps.model.Marker
4
+ import com.google.android.gms.maps.model.Polygon
5
+ import com.google.android.gms.maps.model.Polyline
6
+ import com.rngooglemapsplus.RNMarkerSvg
7
+
8
+ sealed class MapObjectTag(
9
+ open val id: String,
10
+ )
11
+
12
+ data class MarkerTag(
13
+ override val id: String,
14
+ val iconSvg: RNMarkerSvg? = null,
15
+ ) : MapObjectTag(id)
16
+
17
+ data class PolylineTag(
18
+ override val id: String,
19
+ ) : MapObjectTag(id)
20
+
21
+ data class PolygonTag(
22
+ override val id: String,
23
+ ) : MapObjectTag(id)
24
+
25
+ data class CircleTag(
26
+ override val id: String,
27
+ ) : MapObjectTag(id)
28
+
29
+ val Marker.tagData: MarkerTag
30
+ get() =
31
+ (tag as? MarkerTag) ?: run {
32
+ Log.w("MapTag", "Marker without tag detected at $position")
33
+ val fallback = MarkerTag(id = "unknown")
34
+ tag = fallback
35
+ fallback
36
+ }
37
+
38
+ val Marker.idTag: String
39
+ get() = tagData.id
40
+
41
+ var Polyline.tagData: PolylineTag
42
+ get() =
43
+ (tag as? PolylineTag) ?: run {
44
+ Log.w("MapTag", "Polyline without tag detected")
45
+ val fallback = PolylineTag(id = "unknown")
46
+ tag = fallback
47
+ fallback
48
+ }
49
+ set(value) {
50
+ tag = value
51
+ }
52
+
53
+ val Polyline.idTag: String
54
+ get() = tagData.id
55
+
56
+ var Polygon.tagData: PolygonTag
57
+ get() =
58
+ (tag as? PolygonTag) ?: run {
59
+ Log.w("MapTag", "Polygon without tag detected")
60
+ val fallback = PolygonTag(id = "unknown")
61
+ tag = fallback
62
+ fallback
63
+ }
64
+ set(value) {
65
+ tag = value
66
+ }
67
+
68
+ val Polygon.idTag: String
69
+ get() = tagData.id
70
+
71
+ var Circle.tagData: CircleTag
72
+ get() =
73
+ (tag as? CircleTag) ?: run {
74
+ Log.w("MapTag", "Circle without tag detected")
75
+ val fallback = CircleTag(id = "unknown")
76
+ tag = fallback
77
+ fallback
78
+ }
79
+ set(value) {
80
+ tag = value
81
+ }
82
+
83
+ val Circle.idTag: String
84
+ get() = tagData.id
@@ -0,0 +1,14 @@
1
+ package com.rngooglemapsplus.extensions
2
+
3
+ import com.google.android.gms.maps.model.ButtCap
4
+ import com.google.android.gms.maps.model.Cap
5
+ import com.google.android.gms.maps.model.RoundCap
6
+ import com.google.android.gms.maps.model.SquareCap
7
+ import com.rngooglemapsplus.RNLineCapType
8
+
9
+ fun RNLineCapType?.toMapLineCap(): Cap =
10
+ when (this) {
11
+ RNLineCapType.ROUND -> RoundCap()
12
+ RNLineCapType.SQUARE -> SquareCap()
13
+ else -> ButtCap()
14
+ }
@@ -0,0 +1,12 @@
1
+ package com.rngooglemapsplus.extensions
2
+
3
+ import com.google.android.gms.maps.model.JointType
4
+ import com.rngooglemapsplus.RNLineJoinType
5
+
6
+ fun RNLineJoinType?.toMapJointType(): Int =
7
+ when (this) {
8
+ RNLineJoinType.ROUND -> JointType.ROUND
9
+ RNLineJoinType.BEVEL -> JointType.BEVEL
10
+ RNLineJoinType.MITER -> JointType.DEFAULT
11
+ null -> JointType.DEFAULT
12
+ }