react-native-google-maps-plus 0.1.0 → 1.0.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.
- package/GoogleMapsNitro.podspec +34 -0
- package/LICENSE +20 -0
- package/README.md +40 -0
- package/android/CMakeLists.txt +32 -0
- package/android/build.gradle +135 -0
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +8 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/googlemapsnitro/Color.kt +65 -0
- package/android/src/main/java/com/googlemapsnitro/GoogleMapsNitroPackage.kt +35 -0
- package/android/src/main/java/com/googlemapsnitro/GoogleMapsNitroViewImpl.kt +720 -0
- package/android/src/main/java/com/googlemapsnitro/HybridGoogleMapsNitroModule.kt +22 -0
- package/android/src/main/java/com/googlemapsnitro/HybridGoogleMapsNitroView.kt +337 -0
- package/android/src/main/java/com/googlemapsnitro/LocationHandler.kt +205 -0
- package/android/src/main/java/com/googlemapsnitro/MapMarker.kt +145 -0
- package/android/src/main/java/com/googlemapsnitro/MapPolygon.kt +36 -0
- package/android/src/main/java/com/googlemapsnitro/MapPolyline.kt +59 -0
- package/android/src/main/java/com/googlemapsnitro/PermissionHandler.kt +116 -0
- package/android/src/main/java/com/googlemapsnitro/PlayServicesHandler.kt +25 -0
- package/ios/Color.swift +109 -0
- package/ios/GoogleMapNitroViewImpl.swift +590 -0
- package/ios/HybridGoogleMapsNitroModule.swift +27 -0
- package/ios/HybridGoogleMapsNitroView.swift +348 -0
- package/ios/LocationHandler.swift +205 -0
- package/ios/MapHelper.swift +18 -0
- package/ios/MapMarker.swift +207 -0
- package/ios/MapPolygon.swift +55 -0
- package/ios/MapPolyline.swift +83 -0
- package/ios/PermissionHandler.swift +73 -0
- package/lib/module/GoogleMapsNitroModule.nitro.js +4 -0
- package/lib/module/GoogleMapsNitroModule.nitro.js.map +1 -0
- package/lib/module/GoogleMapsNitroView.nitro.js +4 -0
- package/lib/module/GoogleMapsNitroView.nitro.js.map +1 -0
- package/lib/module/index.js +8 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +78 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/GoogleMapsNitroModule.nitro.d.ts +12 -0
- package/lib/typescript/src/GoogleMapsNitroModule.nitro.d.ts.map +1 -0
- package/lib/typescript/src/GoogleMapsNitroView.nitro.d.ts +34 -0
- package/lib/typescript/src/GoogleMapsNitroView.nitro.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +7 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +113 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/nitro.json +28 -0
- package/package.json +13 -3
- package/src/GoogleMapsNitroModule.nitro.ts +13 -0
- package/src/GoogleMapsNitroView.nitro.ts +78 -0
- package/src/index.tsx +24 -0
- package/src/types.ts +174 -0
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
import CoreLocation
|
|
2
|
+
import GoogleMaps
|
|
3
|
+
import UIKit
|
|
4
|
+
|
|
5
|
+
final class GoogleMapsNitroViewImpl: UIView, GMSMapViewDelegate {
|
|
6
|
+
|
|
7
|
+
private let locationHandler: LocationHandler
|
|
8
|
+
private let markerOptions: MapMarkerOptions
|
|
9
|
+
private var mapView: GMSMapView!
|
|
10
|
+
private var mapReady = false
|
|
11
|
+
|
|
12
|
+
private var pendingBuildingEnabled: Bool = false
|
|
13
|
+
private var pendingTrafficEnabled: Bool = false
|
|
14
|
+
private var pendingCustomMapStyle: GMSMapStyle?
|
|
15
|
+
private var pendingInitialCamera: GMSCameraPosition =
|
|
16
|
+
GMSCameraPosition.camera(withLatitude: 0, longitude: 0, zoom: 0)
|
|
17
|
+
private var pendingUserInterfaceStyle = UIUserInterfaceStyle.unspecified
|
|
18
|
+
private var pendingMinZoomLevel: Double = 0.0
|
|
19
|
+
private var pendingMaxZoomLevel: Double = 21.0
|
|
20
|
+
private var pendingMapPadding: RNMapPadding = .init(
|
|
21
|
+
top: 0,
|
|
22
|
+
left: 0,
|
|
23
|
+
bottom: 0,
|
|
24
|
+
right: 0
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
private var pendingPolygons: [(id: String, polygon: GMSPolygon)] = []
|
|
28
|
+
private var pendingPolylines: [(id: String, polyline: GMSPolyline)] = []
|
|
29
|
+
private var pendingMarkers: [(id: String, marker: GMSMarker)] = []
|
|
30
|
+
|
|
31
|
+
private var polygonsById: [String: GMSPolygon] = [:]
|
|
32
|
+
private var polylinesById: [String: GMSPolyline] = [:]
|
|
33
|
+
private var markersById: [String: GMSMarker] = [:]
|
|
34
|
+
|
|
35
|
+
private var cameraMoveReasonIsGesture: Bool = false
|
|
36
|
+
private var lastSubmittedCameraPosition: GMSCameraPosition?
|
|
37
|
+
private var lastSubmittedLocation: CLLocation?
|
|
38
|
+
|
|
39
|
+
var onMapError: ((RNMapErrorCode) -> Void)?
|
|
40
|
+
var onMapReady: ((Bool) -> Void)?
|
|
41
|
+
var onLocationUpdate: ((RNLocation) -> Void)?
|
|
42
|
+
var onLocationError: ((_ error: RNLocationErrorCode) -> Void)?
|
|
43
|
+
var onMapPress: ((RNLatLng) -> Void)?
|
|
44
|
+
var onMarkerPress: ((String) -> Void)?
|
|
45
|
+
var onCameraChangeStart: ((RNRegion, RNCamera, Bool) -> Void)?
|
|
46
|
+
var onCameraChange: ((RNRegion, RNCamera, Bool) -> Void)?
|
|
47
|
+
var onCameraChangeComplete: ((RNRegion, RNCamera, Bool) -> Void)?
|
|
48
|
+
|
|
49
|
+
init(
|
|
50
|
+
frame: CGRect = .zero,
|
|
51
|
+
locationHandler: LocationHandler,
|
|
52
|
+
markerOptions: MapMarkerOptions
|
|
53
|
+
) {
|
|
54
|
+
self.locationHandler = locationHandler
|
|
55
|
+
self.markerOptions = markerOptions
|
|
56
|
+
super.init(frame: frame)
|
|
57
|
+
setupAppLifecycleObservers()
|
|
58
|
+
setupMap()
|
|
59
|
+
|
|
60
|
+
/// wait 1 second if alle setter called
|
|
61
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
|
|
62
|
+
self?.initLocationCallbacks()
|
|
63
|
+
self?.applyPending()
|
|
64
|
+
self?.onMapReady?(true)
|
|
65
|
+
self?.mapReady = true
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private func setupAppLifecycleObservers() {
|
|
70
|
+
NotificationCenter.default.addObserver(
|
|
71
|
+
self,
|
|
72
|
+
selector: #selector(appDidBecomeActive),
|
|
73
|
+
name: UIApplication.didBecomeActiveNotification,
|
|
74
|
+
object: nil
|
|
75
|
+
)
|
|
76
|
+
NotificationCenter.default.addObserver(
|
|
77
|
+
self,
|
|
78
|
+
selector: #selector(appDidEnterBackground),
|
|
79
|
+
name: UIApplication.didEnterBackgroundNotification,
|
|
80
|
+
object: nil
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
required init?(coder: NSCoder) {
|
|
85
|
+
fatalError("init(coder:) has not been implemented")
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@MainActor
|
|
89
|
+
private func setupMap() {
|
|
90
|
+
let options = GMSMapViewOptions()
|
|
91
|
+
options.frame = bounds
|
|
92
|
+
mapView = GMSMapView.init(options: options)
|
|
93
|
+
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
94
|
+
mapView.paddingAdjustmentBehavior = .never
|
|
95
|
+
mapView.delegate = self
|
|
96
|
+
addSubview(mapView)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private func initLocationCallbacks() {
|
|
100
|
+
locationHandler.onUpdate = { [weak self] loc in
|
|
101
|
+
guard let self = self else { return }
|
|
102
|
+
if self.lastSubmittedLocation?.coordinate.latitude
|
|
103
|
+
!= loc.coordinate.latitude
|
|
104
|
+
|| self.lastSubmittedLocation?.coordinate.longitude
|
|
105
|
+
!= loc.coordinate.longitude {
|
|
106
|
+
self.onLocationUpdate?(
|
|
107
|
+
RNLocation(
|
|
108
|
+
RNLatLng(
|
|
109
|
+
latitude: loc.coordinate.latitude,
|
|
110
|
+
longitude: loc.coordinate.longitude
|
|
111
|
+
),
|
|
112
|
+
loc.course
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
self.lastSubmittedLocation = loc
|
|
117
|
+
}
|
|
118
|
+
locationHandler.onError = { [weak self] error in
|
|
119
|
+
self?.onLocationError?(error)
|
|
120
|
+
}
|
|
121
|
+
locationHandler.start()
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@MainActor
|
|
125
|
+
private func applyPending() {
|
|
126
|
+
mapView.padding = UIEdgeInsets(
|
|
127
|
+
top: pendingMapPadding.top,
|
|
128
|
+
left: pendingMapPadding.left,
|
|
129
|
+
bottom: pendingMapPadding.bottom,
|
|
130
|
+
right: pendingMapPadding.right
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
mapView.mapStyle = pendingCustomMapStyle
|
|
134
|
+
mapView.isBuildingsEnabled = pendingBuildingEnabled
|
|
135
|
+
mapView.isTrafficEnabled = pendingTrafficEnabled
|
|
136
|
+
mapView.overrideUserInterfaceStyle = pendingUserInterfaceStyle
|
|
137
|
+
mapView.setMinZoom(
|
|
138
|
+
Float(pendingMinZoomLevel),
|
|
139
|
+
maxZoom: Float(pendingMaxZoomLevel)
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if !pendingMarkers.isEmpty {
|
|
143
|
+
pendingMarkers.forEach {
|
|
144
|
+
addMarkerInternal(id: $0.id, marker: $0.marker)
|
|
145
|
+
}
|
|
146
|
+
pendingMarkers.removeAll()
|
|
147
|
+
}
|
|
148
|
+
if !pendingPolylines.isEmpty {
|
|
149
|
+
pendingPolylines.forEach {
|
|
150
|
+
addPolylineInternal(id: $0.id, polyline: $0.polyline)
|
|
151
|
+
}
|
|
152
|
+
pendingPolylines.removeAll()
|
|
153
|
+
}
|
|
154
|
+
if !pendingPolygons.isEmpty {
|
|
155
|
+
pendingPolygons.forEach {
|
|
156
|
+
addPolygonInternal(id: $0.id, polygon: $0.polygon)
|
|
157
|
+
}
|
|
158
|
+
pendingPolygons.removeAll()
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
var currentCamera: GMSCameraPosition {
|
|
163
|
+
mapView.camera
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@MainActor
|
|
167
|
+
var buildingEnabled: Bool {
|
|
168
|
+
get { mapView.isBuildingsEnabled }
|
|
169
|
+
set {
|
|
170
|
+
pendingBuildingEnabled = newValue
|
|
171
|
+
mapView.isBuildingsEnabled = newValue
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@MainActor
|
|
176
|
+
var trafficEnabled: Bool {
|
|
177
|
+
get { mapView.isTrafficEnabled }
|
|
178
|
+
set {
|
|
179
|
+
pendingTrafficEnabled = newValue
|
|
180
|
+
mapView.isTrafficEnabled = newValue
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@MainActor
|
|
185
|
+
var customMapStyle: GMSMapStyle? {
|
|
186
|
+
get { pendingCustomMapStyle }
|
|
187
|
+
set {
|
|
188
|
+
pendingCustomMapStyle = newValue
|
|
189
|
+
mapView.mapStyle = newValue
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
@MainActor
|
|
194
|
+
var initialCamera: GMSCameraPosition {
|
|
195
|
+
get { pendingInitialCamera }
|
|
196
|
+
set {
|
|
197
|
+
pendingInitialCamera = newValue
|
|
198
|
+
if mapView != nil && !mapReady {
|
|
199
|
+
mapView.camera = newValue
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@MainActor
|
|
205
|
+
var userInterfaceStyle: UIUserInterfaceStyle {
|
|
206
|
+
get { pendingUserInterfaceStyle }
|
|
207
|
+
set {
|
|
208
|
+
pendingUserInterfaceStyle = newValue
|
|
209
|
+
mapView.overrideUserInterfaceStyle = newValue
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@MainActor
|
|
214
|
+
var minZoomLevel: Double {
|
|
215
|
+
get { pendingMinZoomLevel }
|
|
216
|
+
set {
|
|
217
|
+
pendingMinZoomLevel = newValue
|
|
218
|
+
mapView.setMinZoom(Float(newValue), maxZoom: Float(pendingMaxZoomLevel))
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@MainActor
|
|
223
|
+
var maxZoomLevel: Double {
|
|
224
|
+
get { pendingMaxZoomLevel }
|
|
225
|
+
set {
|
|
226
|
+
pendingMaxZoomLevel = newValue
|
|
227
|
+
mapView.setMinZoom(Float(pendingMinZoomLevel), maxZoom: Float(newValue))
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@MainActor
|
|
232
|
+
var mapPadding: RNMapPadding {
|
|
233
|
+
get { pendingMapPadding }
|
|
234
|
+
set {
|
|
235
|
+
pendingMapPadding = newValue
|
|
236
|
+
mapView.padding = UIEdgeInsets(
|
|
237
|
+
top: newValue.top,
|
|
238
|
+
left: newValue.left,
|
|
239
|
+
bottom: newValue.bottom,
|
|
240
|
+
right: newValue.right
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
func setCamera(camera: RNCamera, animated: Bool, durationMS: Double) {
|
|
246
|
+
let current = mapView.camera
|
|
247
|
+
|
|
248
|
+
let zoom = Float(camera.zoom ?? Double(current.zoom))
|
|
249
|
+
let bearing = camera.bearing ?? current.bearing
|
|
250
|
+
let viewingAngle = camera.bearing ?? current.viewingAngle
|
|
251
|
+
|
|
252
|
+
let target = CLLocationCoordinate2D(
|
|
253
|
+
latitude: camera.center?.latitude ?? mapView.camera.target.latitude,
|
|
254
|
+
longitude: camera.center?.longitude ?? mapView.camera.target.longitude
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
let cam = GMSCameraPosition.camera(
|
|
258
|
+
withTarget: target,
|
|
259
|
+
zoom: zoom,
|
|
260
|
+
bearing: bearing,
|
|
261
|
+
viewingAngle: viewingAngle
|
|
262
|
+
)
|
|
263
|
+
if animated {
|
|
264
|
+
withCATransaction(
|
|
265
|
+
disableActions: false,
|
|
266
|
+
duration: durationMS / 1000.0
|
|
267
|
+
) {
|
|
268
|
+
mapView.animate(to: cam)
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
let update = GMSCameraUpdate.setCamera(cam)
|
|
272
|
+
mapView.moveCamera(update)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
func setCameraToCoordinates(
|
|
277
|
+
coordinates: [RNLatLng],
|
|
278
|
+
padding: RNMapPadding,
|
|
279
|
+
animated: Bool,
|
|
280
|
+
durationMS: Double
|
|
281
|
+
) {
|
|
282
|
+
if coordinates.isEmpty {
|
|
283
|
+
return
|
|
284
|
+
}
|
|
285
|
+
var bounds = GMSCoordinateBounds(
|
|
286
|
+
coordinate: CLLocationCoordinate2D(
|
|
287
|
+
latitude: coordinates[0].latitude,
|
|
288
|
+
longitude: coordinates[0].longitude
|
|
289
|
+
),
|
|
290
|
+
coordinate: CLLocationCoordinate2D(
|
|
291
|
+
latitude: coordinates[0].latitude,
|
|
292
|
+
longitude: coordinates[0].longitude
|
|
293
|
+
)
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
for coord in coordinates.dropFirst() {
|
|
297
|
+
bounds = bounds.includingCoordinate(
|
|
298
|
+
CLLocationCoordinate2D(
|
|
299
|
+
latitude: coord.latitude,
|
|
300
|
+
longitude: coord.longitude
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
let insets = UIEdgeInsets(
|
|
306
|
+
top: padding.top,
|
|
307
|
+
left: padding.left,
|
|
308
|
+
bottom: padding.bottom,
|
|
309
|
+
right: padding.right
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
let update = GMSCameraUpdate.fit(bounds, with: insets)
|
|
313
|
+
if animated {
|
|
314
|
+
withCATransaction(
|
|
315
|
+
disableActions: false,
|
|
316
|
+
duration: durationMS / 1000.0
|
|
317
|
+
) {
|
|
318
|
+
mapView.animate(with: update)
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
mapView.moveCamera(update)
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
@MainActor
|
|
326
|
+
func addMarker(id: String, marker: GMSMarker) {
|
|
327
|
+
if mapView == nil {
|
|
328
|
+
pendingMarkers.append((id, marker))
|
|
329
|
+
return
|
|
330
|
+
}
|
|
331
|
+
if let old = markersById.removeValue(forKey: id) { old.map = nil }
|
|
332
|
+
addMarkerInternal(id: id, marker: marker)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
@MainActor
|
|
336
|
+
private func addMarkerInternal(id: String, marker: GMSMarker) {
|
|
337
|
+
marker.userData = id
|
|
338
|
+
marker.map = mapView
|
|
339
|
+
markersById[id] = marker
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
@MainActor
|
|
343
|
+
func updateMarker(id: String, block: @escaping (GMSMarker) -> Void) {
|
|
344
|
+
guard let m = markersById[id] else { return }
|
|
345
|
+
block(m)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
@MainActor
|
|
349
|
+
func removeMarker(id: String) {
|
|
350
|
+
if let m = markersById.removeValue(forKey: id) { m.map = nil }
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
@MainActor
|
|
354
|
+
func clearMarkers() {
|
|
355
|
+
markersById.values.forEach { $0.map = nil }
|
|
356
|
+
markersById.removeAll()
|
|
357
|
+
pendingMarkers.removeAll()
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
@MainActor
|
|
361
|
+
func addPolyline(id: String, polyline: GMSPolyline) {
|
|
362
|
+
if mapView == nil {
|
|
363
|
+
pendingPolylines.append((id, polyline))
|
|
364
|
+
return
|
|
365
|
+
}
|
|
366
|
+
if let old = polylinesById.removeValue(forKey: id) { old.map = nil }
|
|
367
|
+
addPolylineInternal(id: id, polyline: polyline)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
@MainActor
|
|
371
|
+
private func addPolylineInternal(id: String, polyline: GMSPolyline) {
|
|
372
|
+
polyline.map = mapView
|
|
373
|
+
polyline.userData = id
|
|
374
|
+
polylinesById[id] = polyline
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
@MainActor
|
|
378
|
+
func updatePolyline(id: String, block: @escaping (GMSPolyline) -> Void) {
|
|
379
|
+
guard let pl = polylinesById[id] else { return }
|
|
380
|
+
block(pl)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
@MainActor
|
|
384
|
+
func removePolyline(id: String) {
|
|
385
|
+
if let pl = polylinesById.removeValue(forKey: id) { pl.map = nil }
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
@MainActor
|
|
389
|
+
func clearPolylines() {
|
|
390
|
+
polylinesById.values.forEach { $0.map = nil }
|
|
391
|
+
polylinesById.removeAll()
|
|
392
|
+
pendingPolylines.removeAll()
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
@MainActor
|
|
396
|
+
func addPolygon(id: String, polygon: GMSPolygon) {
|
|
397
|
+
if mapView == nil {
|
|
398
|
+
pendingPolygons.append((id, polygon))
|
|
399
|
+
return
|
|
400
|
+
}
|
|
401
|
+
if let old = polygonsById.removeValue(forKey: id) { old.map = nil }
|
|
402
|
+
addPolygonInternal(id: id, polygon: polygon)
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
@MainActor
|
|
406
|
+
private func addPolygonInternal(id: String, polygon: GMSPolygon) {
|
|
407
|
+
polygon.map = mapView
|
|
408
|
+
polygon.userData = id
|
|
409
|
+
polygonsById[id] = polygon
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
@MainActor
|
|
413
|
+
func updatePolygon(id: String, block: @escaping (GMSPolygon) -> Void) {
|
|
414
|
+
guard let pg = polygonsById[id] else { return }
|
|
415
|
+
block(pg)
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@MainActor
|
|
419
|
+
func removePolygon(id: String) {
|
|
420
|
+
if let pg = polygonsById.removeValue(forKey: id) { pg.map = nil }
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
@MainActor
|
|
424
|
+
func clearPolygons() {
|
|
425
|
+
polygonsById.values.forEach { $0.map = nil }
|
|
426
|
+
polygonsById.removeAll()
|
|
427
|
+
pendingPolygons.removeAll()
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
func clearAll() {
|
|
431
|
+
markerOptions.cancelAllIconTasks()
|
|
432
|
+
clearMarkers()
|
|
433
|
+
clearPolylines()
|
|
434
|
+
clearPolygons()
|
|
435
|
+
locationHandler.stop()
|
|
436
|
+
clearMap()
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
@MainActor
|
|
440
|
+
func clearMap() {
|
|
441
|
+
mapView.clear()
|
|
442
|
+
mapView.delegate = nil
|
|
443
|
+
mapView = nil
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
@objc private func appDidBecomeActive() {
|
|
447
|
+
if window != nil {
|
|
448
|
+
locationHandler.start()
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
@objc private func appDidEnterBackground() {
|
|
453
|
+
locationHandler.stop()
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
override func didMoveToWindow() {
|
|
457
|
+
super.didMoveToWindow()
|
|
458
|
+
if window != nil {
|
|
459
|
+
if mapView != nil && mapReady {
|
|
460
|
+
onMapReady?(true)
|
|
461
|
+
}
|
|
462
|
+
locationHandler.start()
|
|
463
|
+
} else {
|
|
464
|
+
locationHandler.stop()
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
deinit {
|
|
469
|
+
NotificationCenter.default.removeObserver(self)
|
|
470
|
+
clearAll()
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
|
|
474
|
+
let visibleRegion = mapView.projection.visibleRegion()
|
|
475
|
+
let bounds = GMSCoordinateBounds(region: visibleRegion)
|
|
476
|
+
|
|
477
|
+
let center = CLLocationCoordinate2D(
|
|
478
|
+
latitude: (bounds.northEast.latitude + bounds.southWest.latitude) / 2.0,
|
|
479
|
+
longitude: (bounds.northEast.longitude + bounds.southWest.longitude) / 2.0
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
let latDelta = bounds.northEast.latitude - bounds.southWest.latitude
|
|
483
|
+
let lngDelta = bounds.northEast.longitude - bounds.southWest.longitude
|
|
484
|
+
|
|
485
|
+
let cp = mapView.camera
|
|
486
|
+
let region = RNRegion(
|
|
487
|
+
center: RNLatLng(center.latitude, center.longitude),
|
|
488
|
+
latitudeDelta: latDelta,
|
|
489
|
+
longitudeDelta: lngDelta
|
|
490
|
+
)
|
|
491
|
+
let cam = RNCamera(
|
|
492
|
+
center: RNLatLng(
|
|
493
|
+
latitude: cp.target.latitude,
|
|
494
|
+
longitude: cp.target.longitude
|
|
495
|
+
),
|
|
496
|
+
zoom: Double(cp.zoom),
|
|
497
|
+
bearing: cp.bearing,
|
|
498
|
+
tilt: cp.viewingAngle
|
|
499
|
+
)
|
|
500
|
+
cameraMoveReasonIsGesture = gesture
|
|
501
|
+
|
|
502
|
+
onCameraChangeStart?(region, cam, gesture)
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
|
|
506
|
+
if let last = lastSubmittedCameraPosition,
|
|
507
|
+
last.target.latitude == position.target.latitude,
|
|
508
|
+
last.target.longitude == position.target.longitude,
|
|
509
|
+
last.zoom == position.zoom,
|
|
510
|
+
last.bearing == position.bearing,
|
|
511
|
+
last.viewingAngle == position.viewingAngle {
|
|
512
|
+
return
|
|
513
|
+
}
|
|
514
|
+
let visibleRegion = mapView.projection.visibleRegion()
|
|
515
|
+
let bounds = GMSCoordinateBounds(region: visibleRegion)
|
|
516
|
+
|
|
517
|
+
let center = CLLocationCoordinate2D(
|
|
518
|
+
latitude: (bounds.northEast.latitude + bounds.southWest.latitude) / 2.0,
|
|
519
|
+
longitude: (bounds.northEast.longitude + bounds.southWest.longitude) / 2.0
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
let latDelta = bounds.northEast.latitude - bounds.southWest.latitude
|
|
523
|
+
let lngDelta = bounds.northEast.longitude - bounds.southWest.longitude
|
|
524
|
+
|
|
525
|
+
let cp = mapView.camera
|
|
526
|
+
let region = RNRegion(
|
|
527
|
+
center: RNLatLng(center.latitude, center.longitude),
|
|
528
|
+
latitudeDelta: latDelta,
|
|
529
|
+
longitudeDelta: lngDelta
|
|
530
|
+
)
|
|
531
|
+
let cam = RNCamera(
|
|
532
|
+
center: RNLatLng(
|
|
533
|
+
latitude: cp.target.latitude,
|
|
534
|
+
longitude: cp.target.longitude
|
|
535
|
+
),
|
|
536
|
+
zoom: Double(cp.zoom),
|
|
537
|
+
bearing: cp.bearing,
|
|
538
|
+
tilt: cp.viewingAngle
|
|
539
|
+
)
|
|
540
|
+
onCameraChange?(region, cam, cameraMoveReasonIsGesture)
|
|
541
|
+
lastSubmittedCameraPosition = position
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {
|
|
545
|
+
let visibleRegion = mapView.projection.visibleRegion()
|
|
546
|
+
let bounds = GMSCoordinateBounds(region: visibleRegion)
|
|
547
|
+
|
|
548
|
+
let center = CLLocationCoordinate2D(
|
|
549
|
+
latitude: (bounds.northEast.latitude + bounds.southWest.latitude) / 2.0,
|
|
550
|
+
longitude: (bounds.northEast.longitude + bounds.southWest.longitude) / 2.0
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
let latDelta = bounds.northEast.latitude - bounds.southWest.latitude
|
|
554
|
+
let lngDelta = bounds.northEast.longitude - bounds.southWest.longitude
|
|
555
|
+
|
|
556
|
+
let cp = mapView.camera
|
|
557
|
+
let region = RNRegion(
|
|
558
|
+
center: RNLatLng(center.latitude, center.longitude),
|
|
559
|
+
latitudeDelta: latDelta,
|
|
560
|
+
longitudeDelta: lngDelta
|
|
561
|
+
)
|
|
562
|
+
let cam = RNCamera(
|
|
563
|
+
center: RNLatLng(
|
|
564
|
+
latitude: cp.target.latitude,
|
|
565
|
+
longitude: cp.target.longitude
|
|
566
|
+
),
|
|
567
|
+
zoom: Double(cp.zoom),
|
|
568
|
+
bearing: cp.bearing,
|
|
569
|
+
tilt: cp.viewingAngle
|
|
570
|
+
)
|
|
571
|
+
onCameraChangeComplete?(region, cam, cameraMoveReasonIsGesture)
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
func mapView(
|
|
575
|
+
_ mapView: GMSMapView,
|
|
576
|
+
didTapAt coordinate: CLLocationCoordinate2D
|
|
577
|
+
) {
|
|
578
|
+
onMapPress?(
|
|
579
|
+
RNLatLng(
|
|
580
|
+
latitude: coordinate.latitude,
|
|
581
|
+
longitude: coordinate.longitude
|
|
582
|
+
))
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
|
|
586
|
+
let id = (marker.userData as? String) ?? "unknown"
|
|
587
|
+
onMarkerPress?(id)
|
|
588
|
+
return true
|
|
589
|
+
}
|
|
590
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
final class HybridGoogleMapsNitroModule: HybridGoogleMapsNitroModuleSpec {
|
|
2
|
+
private let permissionHandler: PermissionHandler
|
|
3
|
+
private let locationHandler: LocationHandler
|
|
4
|
+
|
|
5
|
+
override init() {
|
|
6
|
+
self.permissionHandler = PermissionHandler()
|
|
7
|
+
self.locationHandler = LocationHandler()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
func showLocationDialog() {
|
|
11
|
+
locationHandler.showLocationDialog()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
func openLocationSettings() {
|
|
15
|
+
locationHandler.openLocationSettings()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
func requestLocationPermission()
|
|
19
|
+
-> NitroModules.Promise<RNLocationPermissionResult> {
|
|
20
|
+
return permissionHandler.requestLocationPermission()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
func isGooglePlayServicesAvailable() -> Bool {
|
|
24
|
+
/// not supported
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
}
|