react-native-google-maps-plus 1.6.2 → 1.7.0-dev.10
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/android/proguard-rules.pro +29 -0
- package/android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt +461 -445
- package/android/src/main/java/com/rngooglemapsplus/LocationHandler.kt +5 -8
- package/android/src/main/java/com/rngooglemapsplus/MapCircleBuilder.kt +2 -1
- package/android/src/main/java/com/rngooglemapsplus/MapHeatmapBuilder.kt +1 -1
- package/android/src/main/java/com/rngooglemapsplus/MapHelper.kt +22 -0
- package/android/src/main/java/com/rngooglemapsplus/MapMarkerBuilder.kt +142 -2
- package/android/src/main/java/com/rngooglemapsplus/MapPolygonBuilder.kt +2 -1
- package/android/src/main/java/com/rngooglemapsplus/MapPolylineBuilder.kt.kt +2 -1
- package/android/src/main/java/com/rngooglemapsplus/MapUrlTileOverlayBuilder.kt +40 -0
- package/android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt +93 -33
- package/android/src/main/java/com/rngooglemapsplus/extensions/LatLngBoundsExtension.kt +10 -0
- package/android/src/main/java/com/rngooglemapsplus/extensions/MapObjectTagExtensions.kt +84 -0
- package/android/src/main/java/com/rngooglemapsplus/extensions/RNLatLngBoundsExtension.kt +2 -8
- package/android/src/main/java/com/rngooglemapsplus/extensions/RNMapTypeExtension.kt +13 -0
- package/android/src/main/java/com/rngooglemapsplus/extensions/VisibleRegionExtension.kt +13 -0
- package/ios/GoogleMapViewImpl.swift +182 -48
- package/ios/MapCircleBuilder.swift +2 -0
- package/ios/MapHeatmapBuilder.swift +2 -1
- package/ios/MapMarkerBuilder.swift +54 -1
- package/ios/MapPolygonBuilder.swift +2 -0
- package/ios/MapPolylineBuilder.swift +2 -0
- package/ios/MapUrlTileOverlayBuilder.swift +24 -0
- package/ios/RNGoogleMapsPlusView.swift +75 -10
- package/ios/extensions/GMSCoordinateBounds+Extension.swift +4 -13
- package/ios/extensions/GMSVisibleRegion+Extension.swift +14 -0
- package/ios/extensions/MapObjectTag+Extension.swift +93 -0
- package/ios/extensions/RNLatLngBounds+Extension.swift +4 -4
- package/ios/extensions/RNMapType+Extension.swift +18 -0
- package/lib/module/types.js.map +1 -1
- package/lib/nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json +9 -0
- package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts +19 -8
- package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +18 -5
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/nitrogen/generated/android/RNGoogleMapsPlusOnLoad.cpp +8 -4
- package/nitrogen/generated/android/c++/JFunc_void_RNRegion_RNCamera.hpp +83 -0
- package/nitrogen/generated/android/c++/JFunc_void_RNRegion_RNCamera_bool.hpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string_RNLatLng.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string_std__string_RNLatLng.hpp +77 -0
- package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +265 -73
- package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.hpp +34 -14
- package/nitrogen/generated/android/c++/JRNLatLngBounds.hpp +8 -8
- package/nitrogen/generated/android/c++/JRNMapUiSettings.hpp +11 -3
- package/nitrogen/generated/android/c++/JRNMarker.hpp +7 -3
- package/nitrogen/generated/android/c++/JRNRegion.hpp +23 -13
- package/nitrogen/generated/android/c++/JRNUrlTileOverlay.hpp +78 -0
- package/nitrogen/generated/android/c++/views/JHybridRNGoogleMapsPlusViewStateUpdater.cpp +36 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/Func_void_RNRegion_RNCamera.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/{Func_void_std__optional_std__string_.kt → Func_void_std__string.kt} +12 -12
- 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
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/Func_void_std__string_std__string_RNLatLng.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/HybridRNGoogleMapsPlusViewSpec.kt +147 -21
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLatLngBounds.kt +4 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMapUiSettings.kt +9 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMarker.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNRegion.kt +11 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNUrlTileOverlay.kt +52 -0
- package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.cpp +32 -8
- package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +176 -36
- package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Umbrella.hpp +3 -0
- package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +98 -20
- package/nitrogen/generated/ios/c++/views/HybridRNGoogleMapsPlusViewComponent.mm +45 -0
- package/nitrogen/generated/ios/swift/Func_void_RNRegion_RNCamera.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +6 -6
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string_RNLatLng.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string_std__string_RNLatLng.swift +47 -0
- package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec.swift +18 -7
- package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec_cxx.swift +392 -126
- package/nitrogen/generated/ios/swift/RNLatLngBounds.swift +8 -8
- package/nitrogen/generated/ios/swift/RNMapUiSettings.swift +61 -1
- package/nitrogen/generated/ios/swift/RNMarker.swift +24 -1
- package/nitrogen/generated/ios/swift/RNRegion.swift +33 -11
- package/nitrogen/generated/ios/swift/RNUrlTileOverlay.swift +133 -0
- package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.cpp +20 -0
- package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.hpp +43 -20
- package/nitrogen/generated/shared/c++/RNLatLngBounds.hpp +9 -9
- package/nitrogen/generated/shared/c++/RNMapUiSettings.hpp +10 -2
- package/nitrogen/generated/shared/c++/RNMarker.hpp +6 -2
- package/nitrogen/generated/shared/c++/RNRegion.hpp +24 -13
- package/nitrogen/generated/shared/c++/RNUrlTileOverlay.hpp +96 -0
- package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.cpp +122 -14
- package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.hpp +19 -9
- package/nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json +9 -0
- package/package.json +8 -5
- package/src/RNGoogleMapsPlusView.nitro.ts +21 -7
- package/src/types.ts +19 -5
- package/android/src/main/java/com/rngooglemapsplus/extensions/LatLngBounds.kt +0 -15
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__string_.hpp +0 -76
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__string__RNLatLng.hpp +0 -78
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string__RNLatLng.swift +0 -54
- /package/android/src/main/java/com/rngooglemapsplus/extensions/{RNSize.kt → RNSizeExtension.kt} +0 -0
- /package/android/src/main/java/com/rngooglemapsplus/extensions/{RNSnapshotFormat.kt → RNSnapshotFormatExtension.kt} +0 -0
- /package/android/src/main/java/com/rngooglemapsplus/extensions/{RNSnapshotResultType.kt → RNSnapshotResultTypeExtension.kt} +0 -0
|
@@ -38,7 +38,6 @@ class LocationHandler(
|
|
|
38
38
|
private var priority: Int = PRIORITY_DEFAULT
|
|
39
39
|
private var interval: Long = INTERVAL_DEFAULT
|
|
40
40
|
private var minUpdateInterval: Long = MIN_UPDATE_INTERVAL
|
|
41
|
-
private var lastSubmittedLocation: Location? = null
|
|
42
41
|
private var isActive = false
|
|
43
42
|
|
|
44
43
|
var onUpdate: ((Location) -> Unit)? = null
|
|
@@ -57,6 +56,8 @@ class LocationHandler(
|
|
|
57
56
|
this.interval = interval ?: INTERVAL_DEFAULT
|
|
58
57
|
this.minUpdateInterval = minUpdateInterval ?: MIN_UPDATE_INTERVAL
|
|
59
58
|
buildLocationRequest(this.priority, this.interval, this.minUpdateInterval)
|
|
59
|
+
stop()
|
|
60
|
+
start()
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
fun showLocationDialog() {
|
|
@@ -143,9 +144,8 @@ class LocationHandler(
|
|
|
143
144
|
fusedLocationClientProviderClient.lastLocation
|
|
144
145
|
.addOnSuccessListener(
|
|
145
146
|
OnSuccessListener { location ->
|
|
146
|
-
if (location != null
|
|
147
|
+
if (location != null) {
|
|
147
148
|
onUpdate?.invoke(location)
|
|
148
|
-
lastSubmittedLocation = location
|
|
149
149
|
}
|
|
150
150
|
},
|
|
151
151
|
).addOnFailureListener { e ->
|
|
@@ -157,11 +157,8 @@ class LocationHandler(
|
|
|
157
157
|
override fun onLocationResult(locationResult: LocationResult) {
|
|
158
158
|
val location = locationResult.lastLocation
|
|
159
159
|
if (location != null) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
listener?.onLocationChanged(location)
|
|
163
|
-
onUpdate?.invoke(location)
|
|
164
|
-
}
|
|
160
|
+
listener?.onLocationChanged(location)
|
|
161
|
+
onUpdate?.invoke(location)
|
|
165
162
|
} else {
|
|
166
163
|
onError?.invoke(RNLocationErrorCode.POSITION_UNAVAILABLE)
|
|
167
164
|
}
|
|
@@ -4,6 +4,7 @@ import android.graphics.Color
|
|
|
4
4
|
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
5
5
|
import com.google.android.gms.maps.model.Circle
|
|
6
6
|
import com.google.android.gms.maps.model.CircleOptions
|
|
7
|
+
import com.rngooglemapsplus.extensions.onUi
|
|
7
8
|
import com.rngooglemapsplus.extensions.toColor
|
|
8
9
|
import com.rngooglemapsplus.extensions.toLatLng
|
|
9
10
|
|
|
@@ -23,7 +24,7 @@ class MapCircleBuilder {
|
|
|
23
24
|
prev: RNCircle,
|
|
24
25
|
next: RNCircle,
|
|
25
26
|
circle: Circle,
|
|
26
|
-
) {
|
|
27
|
+
) = onUi {
|
|
27
28
|
if (prev.center.latitude != next.center.latitude ||
|
|
28
29
|
prev.center.longitude != next.center.longitude
|
|
29
30
|
) {
|
|
@@ -19,7 +19,7 @@ class MapHeatmapBuilder {
|
|
|
19
19
|
heatmap.gradient?.let {
|
|
20
20
|
val colors = it.colors.map { c -> c.toColor() }.toIntArray()
|
|
21
21
|
val startPoints = it.startPoints.map { p -> p.toFloat() }.toFloatArray()
|
|
22
|
-
gradient(Gradient(colors, startPoints))
|
|
22
|
+
gradient(Gradient(colors, startPoints, it.colorMapSize.toInt()))
|
|
23
23
|
}
|
|
24
24
|
}.build()
|
|
25
25
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package com.rngooglemapsplus.extensions
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.UiThreadUtil
|
|
4
|
+
import kotlinx.coroutines.CompletableDeferred
|
|
5
|
+
import kotlinx.coroutines.runBlocking
|
|
6
|
+
|
|
7
|
+
inline fun onUi(crossinline block: () -> Unit) {
|
|
8
|
+
if (UiThreadUtil.isOnUiThread()) {
|
|
9
|
+
block()
|
|
10
|
+
} else {
|
|
11
|
+
UiThreadUtil.runOnUiThread { block() }
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
inline fun <T> onUiSync(crossinline block: () -> T): T {
|
|
16
|
+
if (UiThreadUtil.isOnUiThread()) return block()
|
|
17
|
+
val result = CompletableDeferred<T>()
|
|
18
|
+
UiThreadUtil.runOnUiThread {
|
|
19
|
+
runCatching(block).onSuccess(result::complete).onFailure(result::completeExceptionally)
|
|
20
|
+
}
|
|
21
|
+
return runBlocking { result.await() }
|
|
22
|
+
}
|
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
package com.rngooglemapsplus
|
|
2
2
|
|
|
3
|
+
import MarkerTag
|
|
3
4
|
import android.graphics.Bitmap
|
|
5
|
+
import android.graphics.BitmapFactory
|
|
4
6
|
import android.graphics.Canvas
|
|
7
|
+
import android.graphics.Typeface
|
|
8
|
+
import android.graphics.drawable.PictureDrawable
|
|
9
|
+
import android.util.Base64
|
|
5
10
|
import android.util.LruCache
|
|
11
|
+
import android.widget.ImageView
|
|
12
|
+
import android.widget.LinearLayout
|
|
6
13
|
import androidx.core.graphics.createBitmap
|
|
7
14
|
import com.caverock.androidsvg.SVG
|
|
15
|
+
import com.caverock.androidsvg.SVGExternalFileResolver
|
|
8
16
|
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
17
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
9
18
|
import com.google.android.gms.maps.model.BitmapDescriptor
|
|
10
19
|
import com.google.android.gms.maps.model.BitmapDescriptorFactory
|
|
11
20
|
import com.google.android.gms.maps.model.Marker
|
|
12
21
|
import com.google.android.gms.maps.model.MarkerOptions
|
|
13
22
|
import com.rngooglemapsplus.extensions.markerStyleEquals
|
|
23
|
+
import com.rngooglemapsplus.extensions.onUi
|
|
14
24
|
import com.rngooglemapsplus.extensions.styleHash
|
|
15
25
|
import com.rngooglemapsplus.extensions.toLatLng
|
|
16
26
|
import kotlinx.coroutines.CoroutineScope
|
|
@@ -20,9 +30,14 @@ import kotlinx.coroutines.SupervisorJob
|
|
|
20
30
|
import kotlinx.coroutines.ensureActive
|
|
21
31
|
import kotlinx.coroutines.launch
|
|
22
32
|
import kotlinx.coroutines.withContext
|
|
33
|
+
import java.net.HttpURLConnection
|
|
34
|
+
import java.net.URL
|
|
35
|
+
import java.net.URLDecoder
|
|
36
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
23
37
|
import kotlin.coroutines.coroutineContext
|
|
24
38
|
|
|
25
39
|
class MapMarkerBuilder(
|
|
40
|
+
val context: ThemedReactContext,
|
|
26
41
|
private val scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default),
|
|
27
42
|
) {
|
|
28
43
|
private val iconCache =
|
|
@@ -33,7 +48,103 @@ class MapMarkerBuilder(
|
|
|
33
48
|
): Int = 1
|
|
34
49
|
}
|
|
35
50
|
|
|
36
|
-
private val jobsById =
|
|
51
|
+
private val jobsById = ConcurrentHashMap<String, Job>()
|
|
52
|
+
|
|
53
|
+
init {
|
|
54
|
+
// / TODO: refactor with androidsvg 1.5 release
|
|
55
|
+
SVG.registerExternalFileResolver(
|
|
56
|
+
object : SVGExternalFileResolver() {
|
|
57
|
+
override fun resolveImage(filename: String?): Bitmap? {
|
|
58
|
+
if (filename.isNullOrBlank()) return null
|
|
59
|
+
|
|
60
|
+
return runCatching {
|
|
61
|
+
when {
|
|
62
|
+
filename.startsWith("data:image/svg+xml") -> {
|
|
63
|
+
val svgContent =
|
|
64
|
+
if ("base64," in filename) {
|
|
65
|
+
val base64 = filename.substringAfter("base64,")
|
|
66
|
+
String(Base64.decode(base64, Base64.DEFAULT), Charsets.UTF_8)
|
|
67
|
+
} else {
|
|
68
|
+
URLDecoder.decode(filename.substringAfter(","), "UTF-8")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
val svg = SVG.getFromString(svgContent)
|
|
72
|
+
val width = (svg.documentWidth.takeIf { it > 0 } ?: 128f).toInt()
|
|
73
|
+
val height = (svg.documentHeight.takeIf { it > 0 } ?: 128f).toInt()
|
|
74
|
+
|
|
75
|
+
createBitmap(width, height).apply {
|
|
76
|
+
Canvas(this).also(svg::renderToCanvas)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
filename.startsWith("http://") || filename.startsWith("https://") -> {
|
|
81
|
+
val conn =
|
|
82
|
+
(URL(filename).openConnection() as HttpURLConnection).apply {
|
|
83
|
+
connectTimeout = 5000
|
|
84
|
+
readTimeout = 5000
|
|
85
|
+
requestMethod = "GET"
|
|
86
|
+
instanceFollowRedirects = true
|
|
87
|
+
}
|
|
88
|
+
conn.connect()
|
|
89
|
+
|
|
90
|
+
val contentType = conn.contentType ?: ""
|
|
91
|
+
val result =
|
|
92
|
+
if (contentType.contains("svg") || filename.endsWith(".svg")) {
|
|
93
|
+
val svgText = conn.inputStream.bufferedReader().use { it.readText() }
|
|
94
|
+
val innerSvg = SVG.getFromString(svgText)
|
|
95
|
+
val w = innerSvg.documentWidth.takeIf { it > 0 } ?: 128f
|
|
96
|
+
val h = innerSvg.documentHeight.takeIf { it > 0 } ?: 128f
|
|
97
|
+
val bmp = createBitmap(w.toInt(), h.toInt())
|
|
98
|
+
val canvas = Canvas(bmp)
|
|
99
|
+
innerSvg.renderToCanvas(canvas)
|
|
100
|
+
bmp
|
|
101
|
+
} else {
|
|
102
|
+
conn.inputStream.use { BitmapFactory.decodeStream(it) }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
conn.disconnect()
|
|
106
|
+
result
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
else -> null
|
|
110
|
+
}
|
|
111
|
+
}.getOrNull()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
override fun resolveFont(
|
|
115
|
+
fontFamily: String?,
|
|
116
|
+
fontWeight: Int,
|
|
117
|
+
fontStyle: String?,
|
|
118
|
+
): Typeface? {
|
|
119
|
+
if (fontFamily.isNullOrBlank()) return null
|
|
120
|
+
|
|
121
|
+
return runCatching {
|
|
122
|
+
val assetManager = context.assets
|
|
123
|
+
|
|
124
|
+
val candidates =
|
|
125
|
+
listOf(
|
|
126
|
+
"fonts/$fontFamily.ttf",
|
|
127
|
+
"fonts/$fontFamily.otf",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
for (path in candidates) {
|
|
131
|
+
try {
|
|
132
|
+
return Typeface.createFromAsset(assetManager, path)
|
|
133
|
+
} catch (_: Throwable) {
|
|
134
|
+
// / ignore
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
Typeface.create(fontFamily, Typeface.NORMAL)
|
|
139
|
+
}.getOrElse {
|
|
140
|
+
Typeface.create(fontFamily, fontWeight)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
override fun isFormatSupported(mimeType: String?): Boolean = mimeType?.startsWith("image/") == true
|
|
145
|
+
},
|
|
146
|
+
)
|
|
147
|
+
}
|
|
37
148
|
|
|
38
149
|
fun build(
|
|
39
150
|
m: RNMarker,
|
|
@@ -57,7 +168,7 @@ class MapMarkerBuilder(
|
|
|
57
168
|
prev: RNMarker,
|
|
58
169
|
next: RNMarker,
|
|
59
170
|
marker: Marker,
|
|
60
|
-
) {
|
|
171
|
+
) = onUi {
|
|
61
172
|
if (prev.coordinate.latitude != next.coordinate.latitude ||
|
|
62
173
|
prev.coordinate.longitude != next.coordinate.longitude
|
|
63
174
|
) {
|
|
@@ -132,6 +243,10 @@ class MapMarkerBuilder(
|
|
|
132
243
|
if (prev.zIndex != next.zIndex) {
|
|
133
244
|
marker.zIndex = next.zIndex?.toFloat() ?: 0f
|
|
134
245
|
}
|
|
246
|
+
|
|
247
|
+
if (prev.infoWindowIconSvg != next.infoWindowIconSvg) {
|
|
248
|
+
marker.tag = MarkerTag(id = next.id, iconSvg = next.infoWindowIconSvg)
|
|
249
|
+
}
|
|
135
250
|
}
|
|
136
251
|
|
|
137
252
|
fun buildIconAsync(
|
|
@@ -189,6 +304,31 @@ class MapMarkerBuilder(
|
|
|
189
304
|
iconCache.evictAll()
|
|
190
305
|
}
|
|
191
306
|
|
|
307
|
+
fun buildInfoWindow(iconSvg: RNMarkerSvg?): ImageView? {
|
|
308
|
+
val iconSvg = iconSvg ?: return null
|
|
309
|
+
|
|
310
|
+
val svgView =
|
|
311
|
+
ImageView(context).apply {
|
|
312
|
+
layoutParams =
|
|
313
|
+
LinearLayout.LayoutParams(
|
|
314
|
+
iconSvg.width.dpToPx().toInt(),
|
|
315
|
+
iconSvg.height.dpToPx().toInt(),
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
try {
|
|
320
|
+
val svg = SVG.getFromString(iconSvg.svgString)
|
|
321
|
+
svg.setDocumentWidth(iconSvg.width.dpToPx())
|
|
322
|
+
svg.setDocumentHeight(iconSvg.height.dpToPx())
|
|
323
|
+
val drawable = PictureDrawable(svg.renderToPicture())
|
|
324
|
+
svgView.setImageDrawable(drawable)
|
|
325
|
+
} catch (e: Exception) {
|
|
326
|
+
return null
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return svgView
|
|
330
|
+
}
|
|
331
|
+
|
|
192
332
|
private suspend fun renderBitmap(m: RNMarker): Bitmap? {
|
|
193
333
|
m.iconSvg ?: return null
|
|
194
334
|
|
|
@@ -4,6 +4,7 @@ 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.onUi
|
|
7
8
|
import com.rngooglemapsplus.extensions.toColor
|
|
8
9
|
import com.rngooglemapsplus.extensions.toLatLng
|
|
9
10
|
|
|
@@ -30,7 +31,7 @@ class MapPolygonBuilder {
|
|
|
30
31
|
prev: RNPolygon,
|
|
31
32
|
next: RNPolygon,
|
|
32
33
|
poly: Polygon,
|
|
33
|
-
) {
|
|
34
|
+
) = onUi {
|
|
34
35
|
val coordsChanged =
|
|
35
36
|
prev.coordinates.size != next.coordinates.size ||
|
|
36
37
|
!prev.coordinates.zip(next.coordinates).all { (a, b) ->
|
|
@@ -9,6 +9,7 @@ import com.google.android.gms.maps.model.Polyline
|
|
|
9
9
|
import com.google.android.gms.maps.model.PolylineOptions
|
|
10
10
|
import com.google.android.gms.maps.model.RoundCap
|
|
11
11
|
import com.google.android.gms.maps.model.SquareCap
|
|
12
|
+
import com.rngooglemapsplus.extensions.onUi
|
|
12
13
|
import com.rngooglemapsplus.extensions.toColor
|
|
13
14
|
import com.rngooglemapsplus.extensions.toLatLng
|
|
14
15
|
|
|
@@ -34,7 +35,7 @@ class MapPolylineBuilder {
|
|
|
34
35
|
prev: RNPolyline,
|
|
35
36
|
next: RNPolyline,
|
|
36
37
|
polyline: Polyline,
|
|
37
|
-
) {
|
|
38
|
+
) = onUi {
|
|
38
39
|
val coordsChanged =
|
|
39
40
|
prev.coordinates.size != next.coordinates.size ||
|
|
40
41
|
!prev.coordinates.zip(next.coordinates).all { (a, b) ->
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
package com.rngooglemapsplus
|
|
2
|
+
|
|
3
|
+
import com.google.android.gms.maps.model.TileOverlayOptions
|
|
4
|
+
import com.google.android.gms.maps.model.UrlTileProvider
|
|
5
|
+
import java.net.URL
|
|
6
|
+
|
|
7
|
+
class MapUrlTileOverlayBuilder {
|
|
8
|
+
fun build(t: RNUrlTileOverlay): TileOverlayOptions {
|
|
9
|
+
val provider =
|
|
10
|
+
object : UrlTileProvider(
|
|
11
|
+
t.tileSize.toInt(),
|
|
12
|
+
t.tileSize.toInt(),
|
|
13
|
+
) {
|
|
14
|
+
override fun getTileUrl(
|
|
15
|
+
x: Int,
|
|
16
|
+
y: Int,
|
|
17
|
+
zoom: Int,
|
|
18
|
+
): URL? {
|
|
19
|
+
val url =
|
|
20
|
+
t.url
|
|
21
|
+
.replace("{x}", x.toString())
|
|
22
|
+
.replace("{y}", y.toString())
|
|
23
|
+
.replace("{z}", zoom.toString())
|
|
24
|
+
|
|
25
|
+
return try {
|
|
26
|
+
URL(url)
|
|
27
|
+
} catch (e: Exception) {
|
|
28
|
+
null
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
val opts = TileOverlayOptions().tileProvider(provider)
|
|
34
|
+
|
|
35
|
+
t.fadeIn?.let { opts.fadeIn(it) }
|
|
36
|
+
t.zIndex?.let { opts.zIndex(it.toFloat()) }
|
|
37
|
+
t.opacity?.let { opts.transparency(1f - it.toFloat()) }
|
|
38
|
+
return opts
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
package com.rngooglemapsplus
|
|
2
2
|
|
|
3
|
+
import MarkerTag
|
|
3
4
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
4
|
-
import com.facebook.react.bridge.UiThreadUtil
|
|
5
5
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
6
|
import com.google.android.gms.maps.GoogleMapOptions
|
|
7
7
|
import com.google.android.gms.maps.model.MapStyleOptions
|
|
@@ -14,6 +14,7 @@ import com.rngooglemapsplus.extensions.polylineEquals
|
|
|
14
14
|
import com.rngooglemapsplus.extensions.toCameraPosition
|
|
15
15
|
import com.rngooglemapsplus.extensions.toCompressFormat
|
|
16
16
|
import com.rngooglemapsplus.extensions.toFileExtension
|
|
17
|
+
import com.rngooglemapsplus.extensions.toGoogleMapType
|
|
17
18
|
import com.rngooglemapsplus.extensions.toLatLngBounds
|
|
18
19
|
import com.rngooglemapsplus.extensions.toMapColorScheme
|
|
19
20
|
import com.rngooglemapsplus.extensions.toSize
|
|
@@ -28,11 +29,12 @@ class RNGoogleMapsPlusView(
|
|
|
28
29
|
private var locationHandler = LocationHandler(context)
|
|
29
30
|
private var playServiceHandler = PlayServicesHandler(context)
|
|
30
31
|
|
|
31
|
-
private val markerBuilder = MapMarkerBuilder()
|
|
32
|
+
private val markerBuilder = MapMarkerBuilder(context)
|
|
32
33
|
private val polylineBuilder = MapPolylineBuilder()
|
|
33
34
|
private val polygonBuilder = MapPolygonBuilder()
|
|
34
35
|
private val circleBuilder = MapCircleBuilder()
|
|
35
36
|
private val heatmapBuilder = MapHeatmapBuilder()
|
|
37
|
+
private val urlTileOverlayBuilder = MapUrlTileOverlayBuilder()
|
|
36
38
|
|
|
37
39
|
override val view =
|
|
38
40
|
GoogleMapsViewImpl(context, locationHandler, playServiceHandler, markerBuilder)
|
|
@@ -128,9 +130,7 @@ class RNGoogleMapsPlusView(
|
|
|
128
130
|
set(value) {
|
|
129
131
|
if (field == value) return
|
|
130
132
|
field = value
|
|
131
|
-
value?.
|
|
132
|
-
view.mapType = it.value
|
|
133
|
-
}
|
|
133
|
+
view.mapType = value?.toGoogleMapType()
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
override var markers: Array<RNMarker>? = null
|
|
@@ -150,12 +150,19 @@ class RNGoogleMapsPlusView(
|
|
|
150
150
|
when {
|
|
151
151
|
prev == null ->
|
|
152
152
|
markerBuilder.buildIconAsync(id, next) { icon ->
|
|
153
|
-
view.addMarker(
|
|
153
|
+
view.addMarker(
|
|
154
|
+
id,
|
|
155
|
+
markerBuilder.build(next, icon),
|
|
156
|
+
MarkerTag(
|
|
157
|
+
id = id,
|
|
158
|
+
iconSvg = next.infoWindowIconSvg,
|
|
159
|
+
),
|
|
160
|
+
)
|
|
154
161
|
}
|
|
155
162
|
|
|
156
163
|
!prev.markerEquals(next) ->
|
|
157
164
|
view.updateMarker(id) { marker ->
|
|
158
|
-
|
|
165
|
+
markerBuilder.update(prev, next, marker)
|
|
159
166
|
}
|
|
160
167
|
}
|
|
161
168
|
}
|
|
@@ -179,7 +186,7 @@ class RNGoogleMapsPlusView(
|
|
|
179
186
|
|
|
180
187
|
!prev.polylineEquals(next) ->
|
|
181
188
|
view.updatePolyline(id) { polyline ->
|
|
182
|
-
|
|
189
|
+
polylineBuilder.update(prev, next, polyline)
|
|
183
190
|
}
|
|
184
191
|
}
|
|
185
192
|
}
|
|
@@ -204,7 +211,7 @@ class RNGoogleMapsPlusView(
|
|
|
204
211
|
|
|
205
212
|
!prev.polygonEquals(next) ->
|
|
206
213
|
view.updatePolygon(id) { polygon ->
|
|
207
|
-
|
|
214
|
+
polygonBuilder.update(prev, next, polygon)
|
|
208
215
|
}
|
|
209
216
|
}
|
|
210
217
|
}
|
|
@@ -229,7 +236,7 @@ class RNGoogleMapsPlusView(
|
|
|
229
236
|
|
|
230
237
|
!prev.circleEquals(next) ->
|
|
231
238
|
view.updateCircle(id) { circle ->
|
|
232
|
-
|
|
239
|
+
circleBuilder.update(prev, next, circle)
|
|
233
240
|
}
|
|
234
241
|
}
|
|
235
242
|
}
|
|
@@ -264,6 +271,21 @@ class RNGoogleMapsPlusView(
|
|
|
264
271
|
}
|
|
265
272
|
}
|
|
266
273
|
|
|
274
|
+
override var urlTileOverlays: Array<RNUrlTileOverlay>? = null
|
|
275
|
+
set(value) {
|
|
276
|
+
if (field.contentEquals(value)) return
|
|
277
|
+
val prevById = field?.associateBy { it.id } ?: emptyMap()
|
|
278
|
+
val nextById = value?.associateBy { it.id } ?: emptyMap()
|
|
279
|
+
field = value
|
|
280
|
+
(prevById.keys - nextById.keys).forEach { id ->
|
|
281
|
+
view.removeUrlTileOverlay(id)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
nextById.forEach { (id, next) ->
|
|
285
|
+
view.addUrlTileOverlay(id, urlTileOverlayBuilder.build(next))
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
267
289
|
override var locationConfig: RNLocationConfig? = null
|
|
268
290
|
set(value) {
|
|
269
291
|
if (field == value) return
|
|
@@ -281,6 +303,11 @@ class RNGoogleMapsPlusView(
|
|
|
281
303
|
view.onMapReady = cb
|
|
282
304
|
}
|
|
283
305
|
|
|
306
|
+
override var onMapLoaded: ((RNRegion, RNCamera) -> Unit)? = null
|
|
307
|
+
set(cb) {
|
|
308
|
+
view.onMapLoaded = cb
|
|
309
|
+
}
|
|
310
|
+
|
|
284
311
|
override var onLocationUpdate: ((RNLocation) -> Unit)? = null
|
|
285
312
|
set(cb) {
|
|
286
313
|
view.onLocationUpdate = cb
|
|
@@ -296,37 +323,47 @@ class RNGoogleMapsPlusView(
|
|
|
296
323
|
view.onMapPress = cb
|
|
297
324
|
}
|
|
298
325
|
|
|
299
|
-
override var
|
|
326
|
+
override var onMapLongPress: ((RNLatLng) -> Unit)? = null
|
|
327
|
+
set(cb) {
|
|
328
|
+
view.onMapLongPress = cb
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
override var onMarkerPress: ((String) -> Unit)? = null
|
|
300
332
|
set(cb) {
|
|
301
333
|
view.onMarkerPress = cb
|
|
302
334
|
}
|
|
303
335
|
|
|
304
|
-
override var
|
|
336
|
+
override var onPoiPress: ((String, String, RNLatLng) -> Unit)? = null
|
|
337
|
+
set(cb) {
|
|
338
|
+
view.onPoiPress = cb
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
override var onPolylinePress: ((String) -> Unit)? = null
|
|
305
342
|
set(cb) {
|
|
306
343
|
view.onPolylinePress = cb
|
|
307
344
|
}
|
|
308
345
|
|
|
309
|
-
override var onPolygonPress: ((String
|
|
346
|
+
override var onPolygonPress: ((String) -> Unit)? = null
|
|
310
347
|
set(cb) {
|
|
311
348
|
view.onPolygonPress = cb
|
|
312
349
|
}
|
|
313
350
|
|
|
314
|
-
override var onCirclePress: ((String
|
|
351
|
+
override var onCirclePress: ((String) -> Unit)? = null
|
|
315
352
|
set(cb) {
|
|
316
353
|
view.onCirclePress = cb
|
|
317
354
|
}
|
|
318
355
|
|
|
319
|
-
override var onMarkerDragStart: ((String
|
|
356
|
+
override var onMarkerDragStart: ((String, RNLatLng) -> Unit)? = null
|
|
320
357
|
set(cb) {
|
|
321
358
|
view.onMarkerDragStart = cb
|
|
322
359
|
}
|
|
323
360
|
|
|
324
|
-
override var onMarkerDrag: ((String
|
|
361
|
+
override var onMarkerDrag: ((String, RNLatLng) -> Unit)? = null
|
|
325
362
|
set(cb) {
|
|
326
363
|
view.onMarkerDrag = cb
|
|
327
364
|
}
|
|
328
365
|
|
|
329
|
-
override var onMarkerDragEnd: ((String
|
|
366
|
+
override var onMarkerDragEnd: ((String, RNLatLng) -> Unit)? = null
|
|
330
367
|
set(cb) {
|
|
331
368
|
view.onMarkerDragEnd = cb
|
|
332
369
|
}
|
|
@@ -341,6 +378,31 @@ class RNGoogleMapsPlusView(
|
|
|
341
378
|
view.onIndoorLevelActivated = cb
|
|
342
379
|
}
|
|
343
380
|
|
|
381
|
+
override var onInfoWindowPress: ((String) -> Unit)? = null
|
|
382
|
+
set(cb) {
|
|
383
|
+
view.onInfoWindowPress = cb
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
override var onInfoWindowClose: ((String) -> Unit)? = null
|
|
387
|
+
set(cb) {
|
|
388
|
+
view.onInfoWindowClose = cb
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
override var onInfoWindowLongPress: ((String) -> Unit)? = null
|
|
392
|
+
set(cb) {
|
|
393
|
+
view.onInfoWindowLongPress = cb
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
override var onMyLocationPress: ((RNLocation) -> Unit)? = null
|
|
397
|
+
set(cb) {
|
|
398
|
+
view.onMyLocationPress = cb
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
override var onMyLocationButtonPress: ((Boolean) -> Unit)? = null
|
|
402
|
+
set(cb) {
|
|
403
|
+
view.onMyLocationButtonPress = cb
|
|
404
|
+
}
|
|
405
|
+
|
|
344
406
|
override var onCameraChangeStart: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
|
|
345
407
|
set(cb) {
|
|
346
408
|
view.onCameraChangeStart = cb
|
|
@@ -356,19 +418,25 @@ class RNGoogleMapsPlusView(
|
|
|
356
418
|
view.onCameraChangeComplete = cb
|
|
357
419
|
}
|
|
358
420
|
|
|
421
|
+
override fun showMarkerInfoWindow(id: String) {
|
|
422
|
+
view.showMarkerInfoWindow(id)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
override fun hideMarkerInfoWindow(id: String) {
|
|
426
|
+
view.hideMarkerInfoWindow(id)
|
|
427
|
+
}
|
|
428
|
+
|
|
359
429
|
override fun setCamera(
|
|
360
430
|
camera: RNCamera,
|
|
361
431
|
animated: Boolean?,
|
|
362
432
|
durationMs: Double?,
|
|
363
433
|
) {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
)
|
|
371
|
-
}
|
|
434
|
+
val current = view.currentCamera
|
|
435
|
+
view.setCamera(
|
|
436
|
+
camera.toCameraPosition(current),
|
|
437
|
+
animated == true,
|
|
438
|
+
durationMs?.toInt() ?: 3000,
|
|
439
|
+
)
|
|
372
440
|
}
|
|
373
441
|
|
|
374
442
|
override fun setCameraToCoordinates(
|
|
@@ -426,11 +494,3 @@ class RNGoogleMapsPlusView(
|
|
|
426
494
|
|
|
427
495
|
override fun isGooglePlayServicesAvailable(): Boolean = playServiceHandler.isPlayServicesAvailable()
|
|
428
496
|
}
|
|
429
|
-
|
|
430
|
-
private inline fun onUi(crossinline block: () -> Unit) {
|
|
431
|
-
if (UiThreadUtil.isOnUiThread()) {
|
|
432
|
-
block()
|
|
433
|
-
} else {
|
|
434
|
-
UiThreadUtil.runOnUiThread { block() }
|
|
435
|
-
}
|
|
436
|
-
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
package com.rngooglemapsplus.extensions
|
|
2
|
+
|
|
3
|
+
import com.google.android.gms.maps.model.LatLngBounds
|
|
4
|
+
import com.rngooglemapsplus.RNLatLngBounds
|
|
5
|
+
|
|
6
|
+
fun LatLngBounds.toRnLatLngBounds(): RNLatLngBounds =
|
|
7
|
+
RNLatLngBounds(
|
|
8
|
+
northeast = northeast.toRnLatLng(),
|
|
9
|
+
southwest = southwest.toRnLatLng(),
|
|
10
|
+
)
|