react-native-google-maps-plus 1.7.0-dev.15 → 1.7.0-dev.17
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/src/main/java/com/rngooglemapsplus/MapMarkerBuilder.kt +27 -21
- package/ios/GoogleMapViewImpl.swift +4 -1
- package/ios/LocationHandler.swift +3 -1
- package/ios/MapHelper.swift +3 -5
- package/ios/MapMarkerBuilder.swift +98 -98
- package/ios/RNGoogleMapsPlusView.swift +24 -21
- package/ios/extensions/SVGKImage+Extension.swift +22 -0
- package/package.json +1 -1
|
@@ -77,7 +77,10 @@ class MapMarkerBuilder(
|
|
|
77
77
|
val height = (svg.documentHeight.takeIf { it > 0 } ?: 128f).toInt()
|
|
78
78
|
|
|
79
79
|
createBitmap(width, height).apply {
|
|
80
|
-
|
|
80
|
+
density = context.resources.displayMetrics.densityDpi
|
|
81
|
+
Canvas(this).also {
|
|
82
|
+
svg.renderToCanvas(it)
|
|
83
|
+
}
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
|
|
@@ -98,10 +101,12 @@ class MapMarkerBuilder(
|
|
|
98
101
|
val innerSvg = SVG.getFromString(svgText)
|
|
99
102
|
val w = innerSvg.documentWidth.takeIf { it > 0 } ?: 128f
|
|
100
103
|
val h = innerSvg.documentHeight.takeIf { it > 0 } ?: 128f
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
createBitmap(w.toInt(), h.toInt()).apply {
|
|
105
|
+
density = context.resources.displayMetrics.densityDpi
|
|
106
|
+
Canvas(this).also {
|
|
107
|
+
innerSvg.renderToCanvas(it)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
105
110
|
} else {
|
|
106
111
|
conn.inputStream.use { BitmapFactory.decodeStream(it) }
|
|
107
112
|
}
|
|
@@ -328,27 +333,28 @@ class MapMarkerBuilder(
|
|
|
328
333
|
coroutineContext.ensureActive()
|
|
329
334
|
val svg = SVG.getFromString(m.iconSvg.svgString)
|
|
330
335
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
336
|
+
val wPx =
|
|
337
|
+
m.iconSvg.width
|
|
338
|
+
.dpToPx()
|
|
339
|
+
.toInt()
|
|
340
|
+
val hPx =
|
|
341
|
+
m.iconSvg.height
|
|
342
|
+
.dpToPx()
|
|
343
|
+
.toInt()
|
|
334
344
|
|
|
335
345
|
coroutineContext.ensureActive()
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
m.iconSvg.width
|
|
339
|
-
.dpToPx()
|
|
340
|
-
.toInt(),
|
|
341
|
-
m.iconSvg.height
|
|
342
|
-
.dpToPx()
|
|
343
|
-
.toInt(),
|
|
344
|
-
Bitmap.Config.ARGB_8888,
|
|
345
|
-
)
|
|
346
|
+
svg.setDocumentWidth(wPx.toFloat())
|
|
347
|
+
svg.setDocumentHeight(hPx.toFloat())
|
|
346
348
|
|
|
347
349
|
coroutineContext.ensureActive()
|
|
348
|
-
|
|
349
|
-
|
|
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
|
+
}
|
|
350
357
|
|
|
351
|
-
coroutineContext.ensureActive()
|
|
352
358
|
return bmp
|
|
353
359
|
} catch (t: Throwable) {
|
|
354
360
|
try {
|
|
@@ -444,7 +444,10 @@ GMSIndoorDisplayDelegate {
|
|
|
444
444
|
|
|
445
445
|
@MainActor
|
|
446
446
|
func removeMarker(id: String) {
|
|
447
|
-
markersById.removeValue(forKey: id).map {
|
|
447
|
+
markersById.removeValue(forKey: id).map {
|
|
448
|
+
$0.icon = nil
|
|
449
|
+
$0.map = nil
|
|
450
|
+
}
|
|
448
451
|
}
|
|
449
452
|
|
|
450
453
|
@MainActor
|
|
@@ -35,6 +35,8 @@ final class LocationHandler: NSObject, CLLocationManagerDelegate {
|
|
|
35
35
|
|
|
36
36
|
func showLocationDialog() {
|
|
37
37
|
onMainAsync { [weak self] in
|
|
38
|
+
guard let self = self else { return }
|
|
39
|
+
|
|
38
40
|
guard let vc = Self.topMostViewController() else { return }
|
|
39
41
|
let title =
|
|
40
42
|
Bundle.main.object(forInfoDictionaryKey: "LocationNotAvailableTitle")
|
|
@@ -61,7 +63,7 @@ final class LocationHandler: NSObject, CLLocationManagerDelegate {
|
|
|
61
63
|
title: openLocationSettingsButton ?? "Open settings",
|
|
62
64
|
style: .default
|
|
63
65
|
) { _ in
|
|
64
|
-
self
|
|
66
|
+
self.openLocationSettings()
|
|
65
67
|
}
|
|
66
68
|
)
|
|
67
69
|
vc.present(alert, animated: true, completion: nil)
|
package/ios/MapHelper.swift
CHANGED
|
@@ -32,11 +32,9 @@ func onMain(_ block: @escaping @MainActor () -> Void) {
|
|
|
32
32
|
|
|
33
33
|
@inline(__always)
|
|
34
34
|
func onMainAsync(
|
|
35
|
-
_ block: @
|
|
35
|
+
_ block: @escaping @MainActor () async -> Void
|
|
36
36
|
) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
} else {
|
|
40
|
-
Task { @MainActor in await block() }
|
|
37
|
+
Task { @MainActor in
|
|
38
|
+
await block()
|
|
41
39
|
}
|
|
42
40
|
}
|
|
@@ -46,15 +46,35 @@ final class MapMarkerBuilder {
|
|
|
46
46
|
|
|
47
47
|
@MainActor
|
|
48
48
|
func update(_ prev: RNMarker, _ next: RNMarker, _ m: GMSMarker) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
withCATransaction(disableActions: true) {
|
|
50
|
+
|
|
51
|
+
var tracksViewChanges = false
|
|
52
|
+
var tracksInfoWindowChanges = false
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
m.icon = img
|
|
54
|
+
if !prev.coordinateEquals(next) {
|
|
55
|
+
m.position = next.coordinate.toCLLocationCoordinate2D()
|
|
56
|
+
}
|
|
57
57
|
|
|
58
|
+
if !prev.markerStyleEquals(next) {
|
|
59
|
+
self.buildIconAsync(next) { img in
|
|
60
|
+
tracksViewChanges = true
|
|
61
|
+
m.icon = img
|
|
62
|
+
|
|
63
|
+
if !prev.anchorEquals(next) {
|
|
64
|
+
m.groundAnchor = CGPoint(
|
|
65
|
+
x: next.anchor?.x ?? 0.5,
|
|
66
|
+
y: next.anchor?.y ?? 1
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if !prev.infoWindowAnchorEquals(next) {
|
|
71
|
+
m.infoWindowAnchor = CGPoint(
|
|
72
|
+
x: next.infoWindowAnchor?.x ?? 0.5,
|
|
73
|
+
y: next.infoWindowAnchor?.y ?? 0
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
58
78
|
if !prev.anchorEquals(next) {
|
|
59
79
|
m.groundAnchor = CGPoint(
|
|
60
80
|
x: next.anchor?.x ?? 0.5,
|
|
@@ -68,79 +88,70 @@ final class MapMarkerBuilder {
|
|
|
68
88
|
y: next.infoWindowAnchor?.y ?? 0
|
|
69
89
|
)
|
|
70
90
|
}
|
|
71
|
-
|
|
72
|
-
onMainAsync { [weak m] in
|
|
73
|
-
try? await Task.sleep(nanoseconds: 250_000_000)
|
|
74
|
-
m?.tracksViewChanges = false
|
|
75
|
-
}
|
|
76
91
|
}
|
|
77
|
-
|
|
78
|
-
if
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
y: next.anchor?.y ?? 1
|
|
82
|
-
)
|
|
92
|
+
|
|
93
|
+
if prev.title != next.title {
|
|
94
|
+
tracksInfoWindowChanges = true
|
|
95
|
+
m.title = next.title
|
|
83
96
|
}
|
|
84
97
|
|
|
85
|
-
if
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
y: next.infoWindowAnchor?.y ?? 0
|
|
89
|
-
)
|
|
98
|
+
if prev.snippet != next.snippet {
|
|
99
|
+
tracksInfoWindowChanges = true
|
|
100
|
+
m.snippet = next.snippet
|
|
90
101
|
}
|
|
91
|
-
}
|
|
92
102
|
|
|
93
|
-
|
|
103
|
+
if prev.opacity != next.opacity {
|
|
104
|
+
let opacity = Float(next.opacity ?? 1)
|
|
105
|
+
m.opacity = opacity
|
|
106
|
+
m.iconView?.alpha = CGFloat(opacity)
|
|
107
|
+
}
|
|
94
108
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
109
|
+
if prev.flat != next.flat {
|
|
110
|
+
m.isFlat = next.flat ?? false
|
|
111
|
+
}
|
|
99
112
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
113
|
+
if prev.draggable != next.draggable {
|
|
114
|
+
m.isDraggable = next.draggable ?? false
|
|
115
|
+
}
|
|
104
116
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
onMainAsync { [weak m] in
|
|
108
|
-
try? await Task.sleep(nanoseconds: 250_000_000)
|
|
109
|
-
m?.tracksInfoWindowChanges = false
|
|
117
|
+
if prev.rotation != next.rotation {
|
|
118
|
+
m.rotation = next.rotation ?? 0
|
|
110
119
|
}
|
|
111
|
-
}
|
|
112
120
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
m.iconView?.alpha = CGFloat(opacity)
|
|
117
|
-
}
|
|
121
|
+
if prev.zIndex != next.zIndex {
|
|
122
|
+
m.zIndex = Int32(next.zIndex ?? 0)
|
|
123
|
+
}
|
|
118
124
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
if !prev.markerInfoWindowStyleEquals(next) {
|
|
126
|
+
m.tagData = MarkerTag(
|
|
127
|
+
id: next.id,
|
|
128
|
+
iconSvg: next.infoWindowIconSvg
|
|
129
|
+
)
|
|
130
|
+
}
|
|
122
131
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
132
|
+
if tracksViewChanges {
|
|
133
|
+
m.tracksViewChanges = tracksViewChanges
|
|
134
|
+
}
|
|
135
|
+
if tracksInfoWindowChanges {
|
|
136
|
+
m.tracksInfoWindowChanges = tracksInfoWindowChanges
|
|
137
|
+
}
|
|
126
138
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
139
|
+
if tracksViewChanges || tracksInfoWindowChanges {
|
|
140
|
+
onMain { [weak m] in
|
|
141
|
+
guard let m = m else { return }
|
|
130
142
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
143
|
+
if tracksViewChanges {
|
|
144
|
+
m.tracksViewChanges = false
|
|
145
|
+
}
|
|
134
146
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
147
|
+
if tracksInfoWindowChanges {
|
|
148
|
+
m.tracksInfoWindowChanges = false
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
140
152
|
}
|
|
141
153
|
}
|
|
142
154
|
|
|
143
|
-
@MainActor
|
|
144
155
|
func buildIconAsync(
|
|
145
156
|
_ m: RNMarker,
|
|
146
157
|
onReady: @escaping (UIImage?) -> Void
|
|
@@ -158,12 +169,15 @@ final class MapMarkerBuilder {
|
|
|
158
169
|
return
|
|
159
170
|
}
|
|
160
171
|
|
|
172
|
+
let scale = UIScreen.main.scale
|
|
173
|
+
|
|
161
174
|
let task = Task(priority: .userInitiated) { [weak self] in
|
|
162
175
|
guard let self else { return }
|
|
163
|
-
defer {
|
|
176
|
+
defer {
|
|
177
|
+
Task { @MainActor in self.tasks.removeValue(forKey: m.id) }
|
|
178
|
+
}
|
|
164
179
|
|
|
165
|
-
let
|
|
166
|
-
let img = await self.renderUIImage(m, scale)
|
|
180
|
+
let img = self.renderUIImage(m, scale)
|
|
167
181
|
guard let img, !Task.isCancelled else { return }
|
|
168
182
|
|
|
169
183
|
self.iconCache.setObject(img, forKey: key)
|
|
@@ -212,18 +226,11 @@ final class MapMarkerBuilder {
|
|
|
212
226
|
|
|
213
227
|
svgImg.size = size
|
|
214
228
|
|
|
215
|
-
guard let
|
|
229
|
+
guard let finalImage = SVGKExporterUIImage.export(asUIImage: svgImg) else {
|
|
230
|
+
svgImg.clear()
|
|
216
231
|
return nil
|
|
217
232
|
}
|
|
218
|
-
|
|
219
|
-
let fmt = UIGraphicsImageRendererFormat.default()
|
|
220
|
-
fmt.opaque = false
|
|
221
|
-
fmt.scale = UIScreen.main.scale
|
|
222
|
-
let renderer = UIGraphicsImageRenderer(size: size, format: fmt)
|
|
223
|
-
|
|
224
|
-
let finalImage = renderer.image { _ in
|
|
225
|
-
base.draw(in: CGRect(origin: .zero, size: size))
|
|
226
|
-
}
|
|
233
|
+
svgImg.clear()
|
|
227
234
|
|
|
228
235
|
let imageView = UIImageView(image: finalImage)
|
|
229
236
|
imageView.frame = CGRect(origin: .zero, size: size)
|
|
@@ -233,10 +240,10 @@ final class MapMarkerBuilder {
|
|
|
233
240
|
return imageView
|
|
234
241
|
}
|
|
235
242
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
243
|
+
private func renderUIImage(_ m: RNMarker, _ scale: CGFloat) -> UIImage? {
|
|
244
|
+
guard
|
|
245
|
+
let iconSvg = m.iconSvg,
|
|
246
|
+
let data = iconSvg.svgString.data(using: .utf8)
|
|
240
247
|
else { return nil }
|
|
241
248
|
|
|
242
249
|
let size = CGSize(
|
|
@@ -244,28 +251,21 @@ final class MapMarkerBuilder {
|
|
|
244
251
|
height: max(1, CGFloat(iconSvg.height))
|
|
245
252
|
)
|
|
246
253
|
|
|
247
|
-
return
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
svgImg.size = size
|
|
254
|
+
return autoreleasepool { () -> UIImage? in
|
|
255
|
+
guard !Task.isCancelled else { return nil }
|
|
256
|
+
guard let svgImg = SVGKImage(data: data) else { return nil }
|
|
251
257
|
|
|
252
|
-
|
|
253
|
-
guard let base = svgImg.uiImage else { return nil }
|
|
258
|
+
svgImg.size = size
|
|
254
259
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
guard !Task.isCancelled else { return nil }
|
|
259
|
-
let fmt = UIGraphicsImageRendererFormat.default()
|
|
260
|
-
fmt.opaque = false
|
|
261
|
-
fmt.scale = scale
|
|
262
|
-
guard !Task.isCancelled else { return nil }
|
|
263
|
-
let renderer = UIGraphicsImageRenderer(size: size, format: fmt)
|
|
264
|
-
return renderer.image { _ in
|
|
265
|
-
base.draw(in: CGRect(origin: .zero, size: size))
|
|
266
|
-
}
|
|
260
|
+
guard !Task.isCancelled else {
|
|
261
|
+
svgImg.clear()
|
|
262
|
+
return nil
|
|
267
263
|
}
|
|
268
|
-
|
|
264
|
+
|
|
265
|
+
let uiImage = SVGKExporterUIImage.export(asUIImage: svgImg)
|
|
266
|
+
svgImg.clear()
|
|
267
|
+
return uiImage
|
|
268
|
+
}
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
}
|
|
@@ -131,26 +131,26 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
|
|
|
131
131
|
)
|
|
132
132
|
|
|
133
133
|
let removed = Set(prevById.keys).subtracting(nextById.keys)
|
|
134
|
-
withCATransaction(disableActions: true) {
|
|
135
134
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
135
|
+
removed.forEach {
|
|
136
|
+
self.impl.removeMarker(id: $0)
|
|
137
|
+
self.markerBuilder.cancelIconTask($0)
|
|
138
|
+
}
|
|
140
139
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
} else {
|
|
149
|
-
self.markerBuilder.buildIconAsync(next) { icon in
|
|
150
|
-
let marker = self.markerBuilder.build(next, icon: icon)
|
|
151
|
-
self.impl.addMarker(id: id, marker: marker)
|
|
140
|
+
for (id, next) in nextById {
|
|
141
|
+
if let prev = prevById[id] {
|
|
142
|
+
if !prev.markerEquals(next) {
|
|
143
|
+
self.impl.updateMarker(id: id) { [weak self] m in
|
|
144
|
+
guard let self else { return }
|
|
145
|
+
self.markerBuilder.update(prev, next, m)
|
|
152
146
|
}
|
|
153
147
|
}
|
|
148
|
+
} else {
|
|
149
|
+
self.markerBuilder.buildIconAsync(next) { [weak self] icon in
|
|
150
|
+
guard let self else { return }
|
|
151
|
+
let marker = self.markerBuilder.build(next, icon: icon)
|
|
152
|
+
self.impl.addMarker(id: id, marker: marker)
|
|
153
|
+
}
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
}
|
|
@@ -174,7 +174,8 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
|
|
|
174
174
|
for (id, next) in nextById {
|
|
175
175
|
if let prev = prevById[id] {
|
|
176
176
|
if !prev.polylineEquals(next) {
|
|
177
|
-
impl.updatePolyline(id: id) { pl in
|
|
177
|
+
impl.updatePolyline(id: id) { [weak self] pl in
|
|
178
|
+
guard let self else { return }
|
|
178
179
|
self.polylineBuilder.update(prev, next, pl)
|
|
179
180
|
}
|
|
180
181
|
}
|
|
@@ -206,7 +207,8 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
|
|
|
206
207
|
for (id, next) in nextById {
|
|
207
208
|
if let prev = prevById[id] {
|
|
208
209
|
if !prev.polygonEquals(next) {
|
|
209
|
-
impl.updatePolygon(id: id) { pg in
|
|
210
|
+
impl.updatePolygon(id: id) { [weak self] pg in
|
|
211
|
+
guard let self else { return }
|
|
210
212
|
self.polygonBuilder.update(prev, next, pg)
|
|
211
213
|
}
|
|
212
214
|
}
|
|
@@ -235,7 +237,8 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
|
|
|
235
237
|
for (id, next) in nextById {
|
|
236
238
|
if let prev = prevById[id] {
|
|
237
239
|
if !prev.circleEquals(next) {
|
|
238
|
-
impl.updateCircle(id: id) { circle in
|
|
240
|
+
impl.updateCircle(id: id) { [weak self] circle in
|
|
241
|
+
guard let self else { return }
|
|
239
242
|
self.circleBuilder.update(prev, next, circle)
|
|
240
243
|
}
|
|
241
244
|
}
|
|
@@ -422,12 +425,12 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
|
|
|
422
425
|
|
|
423
426
|
@MainActor
|
|
424
427
|
func showMarkerInfoWindow(id: String) {
|
|
425
|
-
impl.showMarkerInfoWindow(id: id)
|
|
428
|
+
impl.showMarkerInfoWindow(id: id)
|
|
426
429
|
}
|
|
427
430
|
|
|
428
431
|
@MainActor
|
|
429
432
|
func hideMarkerInfoWindow(id: String) {
|
|
430
|
-
impl.hideMarkerInfoWindow(id: id)
|
|
433
|
+
impl.hideMarkerInfoWindow(id: id)
|
|
431
434
|
}
|
|
432
435
|
|
|
433
436
|
@MainActor
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import SVGKit
|
|
2
|
+
|
|
3
|
+
extension SVGKImage {
|
|
4
|
+
@inline(__always)
|
|
5
|
+
func clear() {
|
|
6
|
+
caLayerTree?.sublayers?.forEach { $0.removeFromSuperlayer() }
|
|
7
|
+
if let layer = caLayerTree {
|
|
8
|
+
layer.sublayers?.forEach { $0.removeFromSuperlayer() }
|
|
9
|
+
layer.removeFromSuperlayer()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if let dom = domDocument {
|
|
13
|
+
dom.childNodes = nil
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if let root = domTree {
|
|
17
|
+
root.childNodes = nil
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
caLayerTree.sublayers?.removeAll()
|
|
21
|
+
}
|
|
22
|
+
}
|
package/package.json
CHANGED