Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ class GoogleMapsViewImpl(

var onMapError: ((RNMapErrorCode) -> Unit)? = null
var onMapReady: ((Boolean) -> Unit)? = null
var onMapLoaded: ((RNRegion, RNCamera) -> Unit)? = null
var onMapLoaded: ((RNRegion, RNCameraChange) -> Unit)? = null
var onLocationUpdate: ((RNLocation) -> Unit)? = null
var onLocationError: ((RNLocationErrorCode) -> Unit)? = null
var onMapPress: ((RNLatLng) -> Unit)? = null
Expand All @@ -388,9 +388,9 @@ class GoogleMapsViewImpl(
var onInfoWindowLongPress: ((String) -> Unit)? = null
var onMyLocationPress: ((RNLocation) -> Unit)? = null
var onMyLocationButtonPress: ((Boolean) -> Unit)? = null
var onCameraChangeStart: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
var onCameraChange: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
var onCameraChangeComplete: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
var onCameraChangeStart: ((RNRegion, RNCameraChange, Boolean) -> Unit)? = null
var onCameraChange: ((RNRegion, RNCameraChange, Boolean) -> Unit)? = null
var onCameraChangeComplete: ((RNRegion, RNCameraChange, Boolean) -> Unit)? = null

fun showMarkerInfoWindow(id: String) =
onUi {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ class RNGoogleMapsPlusView(
view.onMapReady = cb
}

override var onMapLoaded: ((RNRegion, RNCamera) -> Unit)? = null
override var onMapLoaded: ((RNRegion, RNCameraChange) -> Unit)? = null
set(cb) {
view.onMapLoaded = cb
}
Expand Down Expand Up @@ -405,17 +405,17 @@ class RNGoogleMapsPlusView(
view.onMyLocationButtonPress = cb
}

override var onCameraChangeStart: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
override var onCameraChangeStart: ((RNRegion, RNCameraChange, Boolean) -> Unit)? = null
set(cb) {
view.onCameraChangeStart = cb
}

override var onCameraChange: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
override var onCameraChange: ((RNRegion, RNCameraChange, Boolean) -> Unit)? = null
set(cb) {
view.onCameraChange = cb
}

override var onCameraChangeComplete: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
override var onCameraChangeComplete: ((RNRegion, RNCameraChange, Boolean) -> Unit)? = null
set(cb) {
view.onCameraChangeComplete = cb
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package com.rngooglemapsplus.extensions

import com.google.android.gms.maps.model.CameraPosition
import com.rngooglemapsplus.RNCamera
import com.rngooglemapsplus.RNCameraChange

fun CameraPosition.toRnCamera(): RNCamera =
RNCamera(
fun CameraPosition.toRnCamera(): RNCameraChange =
RNCameraChange(
center = target.toRnLatLng(),
zoom = zoom.toDouble(),
bearing = bearing.toDouble(),
Expand Down
13 changes: 8 additions & 5 deletions ios/GoogleMapViewImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ GMSIndoorDisplayDelegate {

var onMapError: ((RNMapErrorCode) -> Void)?
var onMapReady: ((Bool) -> Void)?
var onMapLoaded: ((RNRegion, RNCamera) -> Void)?
var onMapLoaded: ((RNRegion, RNCameraChange) -> Void)?
var onLocationUpdate: ((RNLocation) -> Void)?
var onLocationError: ((_ error: RNLocationErrorCode) -> Void)?
var onMapPress: ((RNLatLng) -> Void)?
Expand All @@ -281,9 +281,9 @@ GMSIndoorDisplayDelegate {
var onInfoWindowLongPress: ((String) -> Void)?
var onMyLocationPress: ((RNLocation) -> Void)?
var onMyLocationButtonPress: ((Bool) -> Void)?
var onCameraChangeStart: ((RNRegion, RNCamera, Bool) -> Void)?
var onCameraChange: ((RNRegion, RNCamera, Bool) -> Void)?
var onCameraChangeComplete: ((RNRegion, RNCamera, Bool) -> Void)?
var onCameraChangeStart: ((RNRegion, RNCameraChange, Bool) -> Void)?
var onCameraChange: ((RNRegion, RNCameraChange, Bool) -> Void)?
var onCameraChangeComplete: ((RNRegion, RNCameraChange, Bool) -> Void)?

@MainActor
func showMarkerInfoWindow(id: String) {
Expand Down Expand Up @@ -444,7 +444,10 @@ GMSIndoorDisplayDelegate {

@MainActor
func removeMarker(id: String) {
markersById.removeValue(forKey: id).map { $0.map = nil }
markersById.removeValue(forKey: id).map {
$0.icon = nil
$0.map = nil
}
}

@MainActor
Expand Down
4 changes: 3 additions & 1 deletion ios/LocationHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ final class LocationHandler: NSObject, CLLocationManagerDelegate {

func showLocationDialog() {
onMainAsync { [weak self] in
guard let self = self else { return }

guard let vc = Self.topMostViewController() else { return }
let title =
Bundle.main.object(forInfoDictionaryKey: "LocationNotAvailableTitle")
Expand All @@ -61,7 +63,7 @@ final class LocationHandler: NSObject, CLLocationManagerDelegate {
title: openLocationSettingsButton ?? "Open settings",
style: .default
) { _ in
self?.openLocationSettings()
self.openLocationSettings()
}
)
vc.present(alert, animated: true, completion: nil)
Expand Down
8 changes: 3 additions & 5 deletions ios/MapHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,9 @@ func onMain(_ block: @escaping @MainActor () -> Void) {

@inline(__always)
func onMainAsync(
_ block: @MainActor @escaping () async -> Void
_ block: @escaping @MainActor () async -> Void
) {
if Thread.isMainThread {
Task { @MainActor in await block() }
} else {
Task { @MainActor in await block() }
Task { @MainActor in
await block()
}
}
196 changes: 98 additions & 98 deletions ios/MapMarkerBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,35 @@ final class MapMarkerBuilder {

@MainActor
func update(_ prev: RNMarker, _ next: RNMarker, _ m: GMSMarker) {
if !prev.coordinateEquals(next) {
m.position = next.coordinate.toCLLocationCoordinate2D()
}
withCATransaction(disableActions: true) {

var tracksViewChanges = false
var tracksInfoWindowChanges = false

if !prev.markerStyleEquals(next) {
buildIconAsync(next) { img in
m.tracksViewChanges = true
m.icon = img
if !prev.coordinateEquals(next) {
m.position = next.coordinate.toCLLocationCoordinate2D()
}

if !prev.markerStyleEquals(next) {
self.buildIconAsync(next) { img in
tracksViewChanges = true
m.icon = img

if !prev.anchorEquals(next) {
m.groundAnchor = CGPoint(
x: next.anchor?.x ?? 0.5,
y: next.anchor?.y ?? 1
)
}

if !prev.infoWindowAnchorEquals(next) {
m.infoWindowAnchor = CGPoint(
x: next.infoWindowAnchor?.x ?? 0.5,
y: next.infoWindowAnchor?.y ?? 0
)
}
}
} else {
if !prev.anchorEquals(next) {
m.groundAnchor = CGPoint(
x: next.anchor?.x ?? 0.5,
Expand All @@ -68,79 +88,70 @@ final class MapMarkerBuilder {
y: next.infoWindowAnchor?.y ?? 0
)
}

onMainAsync { [weak m] in
try? await Task.sleep(nanoseconds: 250_000_000)
m?.tracksViewChanges = false
}
}
} else {
if !prev.anchorEquals(next) {
m.groundAnchor = CGPoint(
x: next.anchor?.x ?? 0.5,
y: next.anchor?.y ?? 1
)

if prev.title != next.title {
tracksInfoWindowChanges = true
m.title = next.title
}

if !prev.infoWindowAnchorEquals(next) {
m.infoWindowAnchor = CGPoint(
x: next.infoWindowAnchor?.x ?? 0.5,
y: next.infoWindowAnchor?.y ?? 0
)
if prev.snippet != next.snippet {
tracksInfoWindowChanges = true
m.snippet = next.snippet
}
}

var tracksInfoWindowChanges = false
if prev.opacity != next.opacity {
let opacity = Float(next.opacity ?? 1)
m.opacity = opacity
m.iconView?.alpha = CGFloat(opacity)
}

if prev.title != next.title {
tracksInfoWindowChanges = true
m.title = next.title
}
if prev.flat != next.flat {
m.isFlat = next.flat ?? false
}

if prev.snippet != next.snippet {
tracksInfoWindowChanges = true
m.snippet = next.snippet
}
if prev.draggable != next.draggable {
m.isDraggable = next.draggable ?? false
}

if(tracksInfoWindowChanges) {
m.tracksInfoWindowChanges = true
onMainAsync { [weak m] in
try? await Task.sleep(nanoseconds: 250_000_000)
m?.tracksInfoWindowChanges = false
if prev.rotation != next.rotation {
m.rotation = next.rotation ?? 0
}
}

if prev.opacity != next.opacity {
let opacity = Float(next.opacity ?? 1)
m.opacity = opacity
m.iconView?.alpha = CGFloat(opacity)
}
if prev.zIndex != next.zIndex {
m.zIndex = Int32(next.zIndex ?? 0)
}

if prev.flat != next.flat {
m.isFlat = next.flat ?? false
}
if !prev.markerInfoWindowStyleEquals(next) {
m.tagData = MarkerTag(
id: next.id,
iconSvg: next.infoWindowIconSvg
)
}

if prev.draggable != next.draggable {
m.isDraggable = next.draggable ?? false
}
if tracksViewChanges {
m.tracksViewChanges = tracksViewChanges
}
if tracksInfoWindowChanges {
m.tracksInfoWindowChanges = tracksInfoWindowChanges
}

if prev.rotation != next.rotation {
m.rotation = next.rotation ?? 0
}
if tracksViewChanges || tracksInfoWindowChanges {
onMain { [weak m] in
guard let m = m else { return }

if prev.zIndex != next.zIndex {
m.zIndex = Int32(next.zIndex ?? 0)
}
if tracksViewChanges {
m.tracksViewChanges = false
}

if !prev.markerInfoWindowStyleEquals(next) {
m.tagData = MarkerTag(
id: next.id,
iconSvg: next.infoWindowIconSvg
)
if tracksInfoWindowChanges {
m.tracksInfoWindowChanges = false
}
}
}
}
}

@MainActor
func buildIconAsync(
_ m: RNMarker,
onReady: @escaping (UIImage?) -> Void
Expand All @@ -158,12 +169,15 @@ final class MapMarkerBuilder {
return
}

let scale = UIScreen.main.scale

let task = Task(priority: .userInitiated) { [weak self] in
guard let self else { return }
defer { self.tasks.removeValue(forKey: m.id) }
defer {
Task { @MainActor in self.tasks.removeValue(forKey: m.id) }
}

let scale = UIScreen.main.scale
let img = await self.renderUIImage(m, scale)
let img = self.renderUIImage(m, scale)
guard let img, !Task.isCancelled else { return }

self.iconCache.setObject(img, forKey: key)
Expand Down Expand Up @@ -212,18 +226,11 @@ final class MapMarkerBuilder {

svgImg.size = size

guard let base = svgImg.uiImage else {
guard let finalImage = SVGKExporterUIImage.export(asUIImage: svgImg) else {
svgImg.clear()
return nil
}

let fmt = UIGraphicsImageRendererFormat.default()
fmt.opaque = false
fmt.scale = UIScreen.main.scale
let renderer = UIGraphicsImageRenderer(size: size, format: fmt)

let finalImage = renderer.image { _ in
base.draw(in: CGRect(origin: .zero, size: size))
}
svgImg.clear()

let imageView = UIImageView(image: finalImage)
imageView.frame = CGRect(origin: .zero, size: size)
Expand All @@ -233,39 +240,32 @@ final class MapMarkerBuilder {
return imageView
}

@MainActor
private func renderUIImage(_ m: RNMarker, _ scale: CGFloat) async -> UIImage? {
guard let iconSvg = m.iconSvg,
let data = iconSvg.svgString.data(using: .utf8)
private func renderUIImage(_ m: RNMarker, _ scale: CGFloat) -> UIImage? {
guard
let iconSvg = m.iconSvg,
let data = iconSvg.svgString.data(using: .utf8)
else { return nil }

let size = CGSize(
width: max(1, CGFloat(iconSvg.width)),
height: max(1, CGFloat(iconSvg.height))
)

return await Task.detached(priority: .userInitiated) {
autoreleasepool {
guard let svgImg = SVGKImage(data: data) else { return nil }
svgImg.size = size
return autoreleasepool { () -> UIImage? in
guard !Task.isCancelled else { return nil }
guard let svgImg = SVGKImage(data: data) else { return nil }

guard !Task.isCancelled else { return nil }
guard let base = svgImg.uiImage else { return nil }
svgImg.size = size

if let cg = base.cgImage {
return UIImage(cgImage: cg, scale: scale, orientation: .up)
}
guard !Task.isCancelled else { return nil }
let fmt = UIGraphicsImageRendererFormat.default()
fmt.opaque = false
fmt.scale = scale
guard !Task.isCancelled else { return nil }
let renderer = UIGraphicsImageRenderer(size: size, format: fmt)
return renderer.image { _ in
base.draw(in: CGRect(origin: .zero, size: size))
}
guard !Task.isCancelled else {
svgImg.clear()
return nil
}
}.value

let uiImage = SVGKExporterUIImage.export(asUIImage: svgImg)
svgImg.clear()
return uiImage
}
}

}
Loading
Loading