@rnmapbox/maps 10.0.0-beta.64 → 10.0.0-beta.66

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 (90) hide show
  1. package/android/rctmgl/.settings/org.eclipse.buildship.core.prefs +12 -1
  2. package/android/rctmgl/src/main/java-mapboxgl/common/com/mapbox/rctmgl/modules/RCTMGLLocationModule.java +5 -0
  3. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/camera/RCTMGLCamera.kt +1 -1
  4. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/styles/sources/RCTMGLVectorSource.java +3 -6
  5. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/modules/RCTMGLLocationModule.kt +5 -0
  6. package/index.d.ts +37 -166
  7. package/ios/RCTMGL-v10/RCTMGLCamera.swift +113 -0
  8. package/ios/RCTMGL-v10/RCTMGLLocationModule.m +1 -0
  9. package/ios/RCTMGL-v10/RCTMGLLocationModule.swift +12 -3
  10. package/ios/RCTMGL-v10/RCTMGLLogging.swift +13 -0
  11. package/ios/RCTMGL-v10/RCTMGLMarkerView.swift +87 -55
  12. package/ios/RCTMGL-v10/RCTMGLOfflineModule.swift +184 -66
  13. package/ios/RCTMGL-v10/RCTMGLStyleValue.swift +8 -1
  14. package/javascript/components/BackgroundLayer.tsx +91 -0
  15. package/javascript/components/CircleLayer.tsx +97 -0
  16. package/javascript/components/FillExtrusionLayer.tsx +95 -0
  17. package/javascript/components/FillLayer.tsx +91 -0
  18. package/javascript/components/HeatmapLayer.tsx +96 -0
  19. package/javascript/components/NativeUserLocation.tsx +33 -0
  20. package/javascript/components/RasterLayer.tsx +88 -0
  21. package/javascript/components/SkyLayer.tsx +70 -0
  22. package/javascript/components/UserLocation.js +11 -0
  23. package/javascript/modules/location/locationManager.js +23 -2
  24. package/javascript/modules/offline/offlineManager.js +1 -1
  25. package/lib/commonjs/components/BackgroundLayer.js +6 -55
  26. package/lib/commonjs/components/BackgroundLayer.js.map +1 -1
  27. package/lib/commonjs/components/CircleLayer.js +8 -58
  28. package/lib/commonjs/components/CircleLayer.js.map +1 -1
  29. package/lib/commonjs/components/FillExtrusionLayer.js +3 -55
  30. package/lib/commonjs/components/FillExtrusionLayer.js.map +1 -1
  31. package/lib/commonjs/components/FillLayer.js +2 -55
  32. package/lib/commonjs/components/FillLayer.js.map +1 -1
  33. package/lib/commonjs/components/HeatmapLayer.js +3 -56
  34. package/lib/commonjs/components/HeatmapLayer.js.map +1 -1
  35. package/lib/commonjs/components/NativeUserLocation.js +6 -31
  36. package/lib/commonjs/components/NativeUserLocation.js.map +1 -1
  37. package/lib/commonjs/components/RasterLayer.js +1 -53
  38. package/lib/commonjs/components/RasterLayer.js.map +1 -1
  39. package/lib/commonjs/components/SkyLayer.js +2 -43
  40. package/lib/commonjs/components/SkyLayer.js.map +1 -1
  41. package/lib/commonjs/components/UserLocation.js +10 -0
  42. package/lib/commonjs/components/UserLocation.js.map +1 -1
  43. package/lib/commonjs/modules/location/locationManager.js +16 -1
  44. package/lib/commonjs/modules/location/locationManager.js.map +1 -1
  45. package/lib/commonjs/modules/offline/offlineManager.js +1 -1
  46. package/lib/module/components/BackgroundLayer.js +6 -55
  47. package/lib/module/components/BackgroundLayer.js.map +1 -1
  48. package/lib/module/components/CircleLayer.js +7 -57
  49. package/lib/module/components/CircleLayer.js.map +1 -1
  50. package/lib/module/components/FillExtrusionLayer.js +2 -54
  51. package/lib/module/components/FillExtrusionLayer.js.map +1 -1
  52. package/lib/module/components/FillLayer.js +1 -54
  53. package/lib/module/components/FillLayer.js.map +1 -1
  54. package/lib/module/components/HeatmapLayer.js +2 -55
  55. package/lib/module/components/HeatmapLayer.js.map +1 -1
  56. package/lib/module/components/NativeUserLocation.js +4 -30
  57. package/lib/module/components/NativeUserLocation.js.map +1 -1
  58. package/lib/module/components/RasterLayer.js +1 -53
  59. package/lib/module/components/RasterLayer.js.map +1 -1
  60. package/lib/module/components/SkyLayer.js +1 -42
  61. package/lib/module/components/SkyLayer.js.map +1 -1
  62. package/lib/module/components/UserLocation.js +10 -0
  63. package/lib/module/components/UserLocation.js.map +1 -1
  64. package/lib/module/modules/location/locationManager.js +17 -2
  65. package/lib/module/modules/location/locationManager.js.map +1 -1
  66. package/lib/module/modules/offline/offlineManager.js +1 -1
  67. package/lib/typescript/components/BackgroundLayer.d.ts +62 -0
  68. package/lib/typescript/components/BackgroundLayer.d.ts.map +1 -0
  69. package/lib/typescript/components/CircleLayer.d.ts +66 -0
  70. package/lib/typescript/components/CircleLayer.d.ts.map +1 -0
  71. package/lib/typescript/components/FillExtrusionLayer.d.ts +65 -0
  72. package/lib/typescript/components/FillExtrusionLayer.d.ts.map +1 -0
  73. package/{javascript/components/FillLayer.js → lib/typescript/components/FillLayer.d.ts} +28 -57
  74. package/lib/typescript/components/FillLayer.d.ts.map +1 -0
  75. package/lib/typescript/components/HeatmapLayer.d.ts +66 -0
  76. package/lib/typescript/components/HeatmapLayer.d.ts.map +1 -0
  77. package/lib/typescript/components/NativeUserLocation.d.ts +22 -0
  78. package/lib/typescript/components/NativeUserLocation.d.ts.map +1 -0
  79. package/lib/typescript/components/RasterLayer.d.ts +62 -0
  80. package/lib/typescript/components/RasterLayer.d.ts.map +1 -0
  81. package/lib/typescript/components/SkyLayer.d.ts +52 -0
  82. package/lib/typescript/components/SkyLayer.d.ts.map +1 -0
  83. package/package.json +1 -1
  84. package/javascript/components/BackgroundLayer.js +0 -97
  85. package/javascript/components/CircleLayer.js +0 -101
  86. package/javascript/components/FillExtrusionLayer.js +0 -98
  87. package/javascript/components/HeatmapLayer.js +0 -99
  88. package/javascript/components/NativeUserLocation.js +0 -41
  89. package/javascript/components/RasterLayer.js +0 -95
  90. package/javascript/components/SkyLayer.js +0 -80
@@ -1,6 +1,36 @@
1
1
  import MapboxMaps
2
2
  import UIKit
3
3
 
4
+ /// dummy parent of RCTMGLMarkerView, so react-native changes visibility on RCTMGLMarkerView,
5
+ /// and Mapbox changes visibility on RCTMGLMarkerViewParentViewAnnotation
6
+ class RCTMGLMarkerViewParentViewAnnotation : UIView {
7
+ required init(marker: RCTMGLMarkerView) {
8
+ super.init(frame: marker.bounds)
9
+ insertSubview(marker, at: 0)
10
+ }
11
+
12
+ required init?(coder: NSCoder) {
13
+ fatalError("not implented")
14
+ }
15
+
16
+ func remove(marker: RCTMGLMarkerView) {
17
+ marker.removeFromSuperview()
18
+ }
19
+
20
+ func updateSize(_ size: CGSize, oldOffset: CGVector, newOffset: CGVector) {
21
+ let actSize = self.frame.size
22
+ if actSize.width != size.width || actSize.height != size.height {
23
+ let dx = ((size.width/2.0) - newOffset.dx) - ((actSize.width/2.0) - oldOffset.dx)
24
+ let dy = ((size.height/2.0) + newOffset.dy) - ((actSize.height/2.0) + oldOffset.dy)
25
+ print(" => size=\(size) actSize=\(actSize) newOffset=\(newOffset) oldOffset=\(oldOffset) dx=\(dx) dy=\(dy)")
26
+ var frame = self.frame
27
+ frame = frame.offsetBy(dx: -dx, dy: -dy)
28
+ frame.size = size
29
+ self.frame = frame
30
+ }
31
+ }
32
+ }
33
+
4
34
  class RCTMGLMarkerView: UIView, RCTMGLMapComponent {
5
35
  // MARK: - Instance variables
6
36
 
@@ -8,6 +38,7 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent {
8
38
  let id: String = "marker-\(UUID().uuidString)"
9
39
 
10
40
  weak var map: RCTMGLMapView?
41
+ weak var _annotationView: RCTMGLMarkerViewParentViewAnnotation?
11
42
 
12
43
  var didAddToMap = false
13
44
 
@@ -31,13 +62,7 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent {
31
62
 
32
63
  @objc var isSelected: Bool = false {
33
64
  didSet {
34
- let hasBecomeSelected = isSelected && !oldValue
35
-
36
- if hasBecomeSelected {
37
- setSelected()
38
- } else {
39
- update()
40
- }
65
+ update()
41
66
  }
42
67
  }
43
68
 
@@ -89,36 +114,33 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent {
89
114
 
90
115
  // MARK: - React methods
91
116
 
117
+ override var isHidden: Bool {
118
+ get {
119
+ return super.isHidden
120
+ }
121
+ set {
122
+ super.isHidden = newValue
123
+ }
124
+ }
125
+
92
126
  override func reactSetFrame(_ frame: CGRect) {
93
127
  let prev = self.frame
94
128
  var next = frame
95
129
 
96
130
  let frameDidChange = !next.equalTo(prev)
97
- if (frameDidChange) {
98
- if prev.minX == 0 || prev.minY == 0 {
99
- // Start the view offscreen to make it invisible until the annotation manager sets it to
100
- // the correct point on the map.
101
- next = CGRect(
102
- x: -10000,
103
- y: -10000,
104
- width: next.width,
105
- height: next.height
106
- )
107
- } else {
108
- // Calculate the next position to temporarily place the view before the annotation manager
109
- // sets it to the correct point on the map.
110
- let dx = (next.width - prev.width) / 2
111
- let dy = (next.height - prev.height) / 2
112
- next = CGRect(
113
- x: prev.minX - dx,
114
- y: prev.minY - dy,
115
- width: next.width,
116
- height: next.height
117
- )
118
- }
131
+ if frameDidChange {
132
+ next = CGRect(
133
+ x: 0,
134
+ y: 0,
135
+ width: next.width,
136
+ height: next.height
137
+ )
119
138
  }
120
-
139
+
121
140
  super.reactSetFrame(next)
141
+ if frameDidChange {
142
+ annotationView.updateSize(next.size, oldOffset:calcOffset(size: prev.size), newOffset: calcOffset(size: next.size))
143
+ }
122
144
  addOrUpdate()
123
145
  }
124
146
 
@@ -156,7 +178,7 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent {
156
178
 
157
179
  do {
158
180
  let options = getOptions()
159
- try annotationManager.add(self, id: id, options: options)
181
+ try annotationManager.add(annotationView, id: id, options: options)
160
182
  didAddToMap = true
161
183
  } catch {
162
184
  Logger.log(level: .error, message: "[MarkerView] Error adding annotation", error: error)
@@ -174,27 +196,17 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent {
174
196
 
175
197
  do {
176
198
  let options = getOptions()
177
- try annotationManager.update(self, options: options)
199
+ try annotationManager.update(annotationView, options: options)
178
200
  } catch {
179
201
  Logger.log(level: .error, message: "[MarkerView] Error updating annotation", error: error)
180
202
  }
181
203
  }
182
204
 
183
- /// There is a Mapbox bug where `selected` does not cause the marker to move to the front, so we can't simply update the component.
184
- /// This forces that effect. See https://github.com/mapbox/mapbox-maps-ios/issues/1599.
185
- private func setSelected() {
186
- if let options = annotationManager?.options(for: self) {
187
- do {
188
- annotationManager?.remove(self)
189
- try annotationManager?.add(self, id: id, options: options)
190
- } catch {
191
- Logger.log(level: .error, message: "[MarkerView] Error selecting annotation", error: error)
192
- }
193
- }
194
- }
195
-
196
205
  private func remove() {
197
- annotationManager?.remove(self)
206
+ annotationManager?.remove(annotationView)
207
+ annotationView.remove(marker: self)
208
+ self._annotationView = nil
209
+ didAddToMap = false
198
210
  }
199
211
 
200
212
  // MARK: - Helper functions
@@ -205,29 +217,49 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent {
205
217
  geometry = Geometry.point(point)
206
218
  }
207
219
 
208
- let offset = getOffset()
220
+ let size = self.bounds.size
221
+ let offset = calcOffset(size: size)
209
222
 
210
223
  let options = ViewAnnotationOptions(
211
224
  geometry: geometry,
212
- width: self.bounds.width,
213
- height: self.bounds.height,
225
+ width: size.width,
226
+ height: size.height,
214
227
  allowOverlap: allowOverlap,
215
228
  offsetX: offset.dx,
216
- offsetY: offset.dy
229
+ offsetY: offset.dy,
230
+ selected: isSelected
217
231
  )
218
232
  return options
219
233
  }
220
234
 
221
- private func getOffset() -> CGVector {
235
+ private func calcOffset(size: CGSize) -> CGVector {
222
236
  guard let anchor = anchor, let anchorX = anchor["x"]?.CGFloat, let anchorY = anchor["y"]?.CGFloat else {
223
237
  return .zero
224
238
  }
225
239
 
226
- // Create a modified offset, normalized from 0..1 to -1..1 and scaled to
227
- // the view size.
228
- let x = (anchorX * 2 - 1) * (self.bounds.width / 2) * -1
229
- let y = (anchorY * 2 - 1) * (self.bounds.height / 2)
240
+ let x = (anchorX * 2 - 1) * (size.width / 2) * -1
241
+ let y = (anchorY * 2 - 1) * (size.height / 2)
230
242
 
231
243
  return CGVector(dx: x, dy: y)
232
244
  }
245
+
246
+ var annotationView : RCTMGLMarkerViewParentViewAnnotation {
247
+ if let result = _annotationView {
248
+ return result
249
+ }
250
+ let result = RCTMGLMarkerViewParentViewAnnotation(marker: self)
251
+ _annotationView = result
252
+ return result
253
+ }
254
+
255
+ @objc override func didMoveToSuperview() {
256
+ // React tends to add back us to our original superview,
257
+ // https://github.com/facebook/react-native/blob/11ece22fc6955d169def9ef9f2809c24bc457ba8/React/Views/UIView%2BReact.m#L172-L177
258
+ // fix that if we see that
259
+ if let expectedParent = _annotationView {
260
+ if superview != nil && superview != expectedParent {
261
+ expectedParent.addSubview(self)
262
+ }
263
+ }
264
+ }
233
265
  }
@@ -11,10 +11,14 @@ extension Date {
11
11
  }
12
12
  }
13
13
 
14
+
15
+
14
16
  @objc(RCTMGLOfflineModule)
15
17
  class RCTMGLOfflineModule: RCTEventEmitter {
16
18
  var hasListeners = false
17
19
 
20
+ static let RNMapboxInfoMetadataKey = "_rnmapbox"
21
+
18
22
  enum Callbacks : String {
19
23
  case error = "MapboOfflineRegionError"
20
24
  case progress = "MapboxOfflineRegionProgress"
@@ -37,15 +41,78 @@ class RCTMGLOfflineModule: RCTEventEmitter {
37
41
  }()
38
42
 
39
43
  struct TileRegionPack {
44
+ init(name: String, state: State = .unknown, progress: TileRegionLoadProgress? = nil, metadata: [String:Any]) {
45
+ self.name = name
46
+ self.progress = progress
47
+ self.metadata = metadata
48
+ self.state = state
49
+
50
+ if let rnMetadata = metadata[RNMapboxInfoMetadataKey] as? [String:Any] {
51
+ if let styleURI = rnMetadata["styleURI"] as? String {
52
+ self.styleURI = StyleURI(rawValue: styleURI)
53
+ }
54
+ if let bounds = rnMetadata["bounds"] as? JSONObject {
55
+ self.bounds = logged("RCTMGLOfflineModule.TileRegionPack: cannot decode bounds") {
56
+ let jsonData = try JSONSerialization.data(withJSONObject: bounds)
57
+ return try JSONDecoder().decode(Geometry.self, from: jsonData)
58
+ }
59
+ }
60
+ if let zoomRange = rnMetadata["zoomRange"] as? JSONObject {
61
+ self.zoomRange = logged("RCTMGLOfflineModule.TileRegionPack: cannot decode zoomRange") {
62
+ let jsonData = try JSONSerialization.data(withJSONObject: zoomRange)
63
+ return try JSONDecoder().decode(ClosedRange<UInt8>.self, from: jsonData)
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ init(name: String,
70
+ state: State = .unknown,
71
+ styleURI: StyleURI,
72
+ bounds: Geometry,
73
+ zoomRange: ClosedRange<UInt8>,
74
+ metadata: [String:Any]) {
75
+ self.name = name
76
+ self.progress = nil
77
+ self.cancelable = nil
78
+ self.state = state
79
+
80
+ self.styleURI = styleURI
81
+ self.bounds = bounds
82
+ self.zoomRange = zoomRange
83
+
84
+ var metadata = metadata
85
+ metadata[RNMapboxInfoMetadataKey] = [
86
+ "styleURI": styleURI.rawValue,
87
+ "bounds": logged("RCTMGLOfflineModule.TileRegionPack: cannot encode bounds") { try JSONSerialization.jsonObject(with: try! JSONEncoder().encode(bounds)) },
88
+ "zoomRange": logged("RCTMGLOfflineModule.TileRegionPack: cannot encode zoomRange") { try JSONSerialization.jsonObject(with: try! JSONEncoder().encode(zoomRange))}
89
+ ]
90
+ self.metadata = metadata
91
+ }
92
+
40
93
  var name: String
41
94
  var cancelable: Cancelable? = nil
42
95
  var progress : TileRegionLoadProgress? = nil
43
96
  var state : State = .inactive
44
97
  var metadata : [String:Any]? = nil
98
+
99
+ // Stored in metadata for resume functionality:
100
+ var bounds: Geometry? = nil
101
+ var zoomRange: ClosedRange<UInt8>? = nil
102
+ var styleURI: StyleURI? = nil
45
103
  }
46
104
 
47
105
  lazy var tileRegionPacks : [String: TileRegionPack] = [:]
48
106
 
107
+ var progressEventThrottle : (
108
+ waitBetweenEvents: Double?,
109
+ lastSentTimestamp: Double?,
110
+ lastSentState: State?
111
+ ) = (
112
+ 300,
113
+ nil,
114
+ nil
115
+ )
49
116
 
50
117
  @objc override
51
118
  func startObserving() {
@@ -107,7 +174,7 @@ class RCTMGLOfflineModule: RCTEventEmitter {
107
174
  if let expires = region.expires {
108
175
  result["expires"] = expires.toJSONString()
109
176
  }
110
-
177
+
111
178
  result["metadata"] = String(data:try! JSONSerialization.data(withJSONObject: metadata, options: [.prettyPrinted]), encoding: .utf8)
112
179
 
113
180
  result["bounds"] = jsonBounds
@@ -173,9 +240,9 @@ class RCTMGLOfflineModule: RCTEventEmitter {
173
240
  let ret = self.convertRegionToJSON(region: region, geometry: geometry, metadata: metadata)
174
241
  var pack = self.tileRegionPacks[region.id] ?? TileRegionPack(
175
242
  name: region.id,
176
- progress: self.toProgress(region: region),
177
243
  state: .unknown,
178
- metadata: metadata
244
+ progress: self.toProgress(region: region),
245
+ metadata: logged("RCTMGLOfflineModule.getPacks metadata is null") { metadata } ?? [:]
179
246
  )
180
247
 
181
248
  if ((region.completedResourceCount == region.completedResourceSize)) {
@@ -301,12 +368,8 @@ class RCTMGLOfflineModule: RCTEventEmitter {
301
368
  RCTMGLEvent(type: .offlineProgress, payload: self._makeRegionStatusPayload(name, progress: progress, state: state, metadata: nil))
302
369
  }
303
370
 
304
- func shouldSendProgressEvent() -> Bool {
305
- return true
306
- }
307
-
308
371
  func offlinePackProgressDidChange(progress: TileRegionLoadProgress, metadata: [String:Any], state: State) {
309
- if self.shouldSendProgressEvent() {
372
+ if self.shouldSendProgressEvent(progress: progress, state: state) {
310
373
  let event = makeProgressEvent(metadata["name"] as! String, progress: progress, state: state)
311
374
  self._sendEvent(Callbacks.progress.rawValue, event: event)
312
375
  }
@@ -322,9 +385,9 @@ class RCTMGLOfflineModule: RCTEventEmitter {
322
385
  DispatchQueue.main.async {
323
386
  do {
324
387
  let metadataStr = options["metadata"] as! String
325
- let metadata = try JSONSerialization.jsonObject(with: metadataStr.data(using: .utf8)!, options: []) as! [String:Any]
388
+ var metadata = try JSONSerialization.jsonObject(with: metadataStr.data(using: .utf8)!, options: []) as! [String:Any]
389
+ metadata["styleURI"] = options["styleURL"]
326
390
  let id = metadata["name"] as! String
327
- let stylePackLoadOptions = StylePackLoadOptions(glyphsRasterizationMode: .ideographsRasterizedLocally, metadata: metadata)
328
391
 
329
392
  let boundsStr = options["bounds"] as! String
330
393
  let boundsData = boundsStr.data(using: .utf8)
@@ -332,53 +395,16 @@ class RCTMGLOfflineModule: RCTEventEmitter {
332
395
 
333
396
  var bounds = self.convertPointPairToBounds(RCTMGLFeatureUtils.fcToGeomtry(boundsFC))
334
397
 
335
- let descriptorOptions = TilesetDescriptorOptions(
336
- styleURI: StyleURI(rawValue: options["styleURL"] as! String)!,
337
- zoomRange: (options["minZoom"] as! NSNumber).uint8Value...(options["maxZoom"] as! NSNumber).uint8Value,
338
- stylePackOptions: stylePackLoadOptions
339
- )
340
- let tilesetDescriptor = self.offlineManager.createTilesetDescriptor(for: descriptorOptions)
341
-
342
- let loadOptions = TileRegionLoadOptions(
343
- geometry: bounds, // RCTMGLFeatureUtils.geometryToGeometry(bounds),
344
- descriptors: [tilesetDescriptor],
345
- metadata: metadata,
346
- acceptExpired: true,
347
- networkRestriction: .none,
348
- averageBytesPerSecond: nil)
349
-
350
398
  let actPack = RCTMGLOfflineModule.TileRegionPack(
351
399
  name: id,
352
- progress: nil,
353
- state: .inactive
400
+ styleURI: StyleURI(rawValue: options["styleURL"] as! String)!,
401
+ bounds: bounds,
402
+ zoomRange: (options["minZoom"] as! NSNumber).uint8Value...(options["maxZoom"] as! NSNumber).uint8Value,
403
+ metadata: metadata
354
404
  )
355
405
  self.tileRegionPacks[id] = actPack
406
+ self.startLoading(pack: actPack)
356
407
 
357
- var lastProgress : TileRegionLoadProgress? = nil
358
- let task = self.tileStore.loadTileRegion(forId: id, loadOptions: loadOptions!, progress: {
359
- progress in
360
- lastProgress = progress
361
- self.tileRegionPacks[id]!.progress = progress
362
- self.tileRegionPacks[id]!.state = .active
363
- self.offlinePackProgressDidChange(progress: progress, metadata: metadata, state: .active)
364
- }) { result in
365
- switch result {
366
- case .success(let value):
367
- DispatchQueue.main.async {
368
- if let progess = lastProgress {
369
- self.offlinePackProgressDidChange(progress: progess, metadata: metadata, state: .complete)
370
- }
371
- self.tileRegionPacks[id]!.state = .complete
372
- }
373
- case .failure(let error):
374
- DispatchQueue.main.async {
375
- self.tileRegionPacks[id]!.state = .inactive
376
- self.offlinePackDidReceiveError(name: id, error: error)
377
- }
378
- }
379
- }
380
-
381
- self.tileRegionPacks[id]!.cancelable = task
382
408
  resolver([
383
409
  "bounds": boundsStr,
384
410
  "metadata": String(data:try! JSONSerialization.data(withJSONObject: metadata, options: [.prettyPrinted]), encoding: .utf8)
@@ -389,10 +415,72 @@ class RCTMGLOfflineModule: RCTEventEmitter {
389
415
  }
390
416
  }
391
417
 
418
+ func startLoading(pack: TileRegionPack) {
419
+ let id = pack.name
420
+ guard let bounds = pack.bounds else {
421
+ RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there are no bounds in pack")
422
+ return
423
+ }
424
+ guard let zoomRange = pack.zoomRange else {
425
+ RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there is no zoom range in pack")
426
+ return
427
+ }
428
+ guard let styleURI = pack.styleURI else {
429
+ RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there is no styleURI in pack")
430
+ return
431
+ }
432
+ guard let metadata = pack.metadata else {
433
+ RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there is no metadata in pack")
434
+ return
435
+ }
436
+
437
+ let stylePackLoadOptions = StylePackLoadOptions(glyphsRasterizationMode: .ideographsRasterizedLocally, metadata: pack.metadata)
438
+
439
+ let descriptorOptions = TilesetDescriptorOptions(
440
+ styleURI: styleURI,
441
+ zoomRange: zoomRange,
442
+ stylePackOptions: stylePackLoadOptions
443
+ )
444
+ let tilesetDescriptor = self.offlineManager.createTilesetDescriptor(for: descriptorOptions)
445
+
446
+ let loadOptions = TileRegionLoadOptions(
447
+ geometry: bounds, // RCTMGLFeatureUtils.geometryToGeometry(bounds),
448
+ descriptors: [tilesetDescriptor],
449
+ metadata: metadata,
450
+ acceptExpired: true,
451
+ networkRestriction: .none,
452
+ averageBytesPerSecond: nil)
453
+
454
+ var lastProgress : TileRegionLoadProgress? = nil
455
+ let task = self.tileStore.loadTileRegion(forId: id, loadOptions: loadOptions!, progress: {
456
+ progress in
457
+ lastProgress = progress
458
+ self.tileRegionPacks[id]!.progress = progress
459
+ self.tileRegionPacks[id]!.state = .active
460
+ self.offlinePackProgressDidChange(progress: progress, metadata: metadata, state: .active)
461
+ }) { result in
462
+ switch result {
463
+ case .success(let value):
464
+ DispatchQueue.main.async {
465
+ if let progess = lastProgress {
466
+ self.offlinePackProgressDidChange(progress: progess, metadata: metadata, state: .complete)
467
+ }
468
+ self.tileRegionPacks[id]!.state = .complete
469
+ }
470
+ case .failure(let error):
471
+ DispatchQueue.main.async {
472
+ self.tileRegionPacks[id]!.state = .inactive
473
+ self.offlinePackDidReceiveError(name: id, error: error)
474
+ }
475
+ }
476
+ }
477
+ self.tileRegionPacks[id]!.cancelable = task
478
+ }
479
+
392
480
  func _getPack(fromName: String) -> TileRegionPack? {
393
481
  return self.tileRegionPacks[fromName]
394
482
  }
395
-
483
+
396
484
  @objc
397
485
  func getPackStatus(_ name: String,
398
486
  resolver: @escaping RCTPromiseResolveBlock,
@@ -408,12 +496,10 @@ class RCTMGLOfflineModule: RCTEventEmitter {
408
496
  Logger.log(level:.error, message: "Unable to fetch metadata for \(name)")
409
497
  rejecter("RCTMGLOfflineModule.getPackStatus", error.localizedDescription, error)
410
498
  case .success(let metadata):
411
- var pack = self.tileRegionPacks[name] ?? TileRegionPack(name: name)
412
- if let metadata = metadata as? [String:Any] {
413
- pack.metadata = metadata
414
- } else {
415
- Logger.log(level:.error, message: "Unexpected metadata format for \(name) \(metadata)")
416
- }
499
+ var pack = self.tileRegionPacks[name] ?? TileRegionPack(
500
+ name: name,
501
+ metadata: logged("RCTMGLOfflineModule.getPackStatus") { metadata as? [String:Any] } ?? [:]
502
+ )
417
503
  self.tileRegionPacks[name] = pack
418
504
  resolver(self._makeRegionStatusPayload(pack: pack))
419
505
  }
@@ -424,7 +510,9 @@ class RCTMGLOfflineModule: RCTEventEmitter {
424
510
  @objc
425
511
  func resumePackDownload(_ name: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock)
426
512
  {
427
- //V10todo start download again
513
+ if let pack = _getPack(fromName: name) {
514
+ self.startLoading(pack: pack)
515
+ }
428
516
  }
429
517
 
430
518
  @objc
@@ -440,12 +528,7 @@ class RCTMGLOfflineModule: RCTEventEmitter {
440
528
 
441
529
  @objc
442
530
  func setTileCountLimit(_ limit: NSNumber) {
443
- //v10todo
444
- }
445
-
446
- @objc
447
- func setProgressEventThrottle(_ throttleValue: NSNumber) {
448
- // v10todo improve progress event listener
531
+ RCTMGLLogWarn("setTileCountLimit is not yet implemented on v10")
449
532
  }
450
533
 
451
534
 
@@ -486,3 +569,38 @@ class RCTMGLOfflineModule: RCTEventEmitter {
486
569
  }
487
570
  }
488
571
  }
572
+
573
+ // MARK: progress throttle
574
+
575
+ extension RCTMGLOfflineModule {
576
+ @objc
577
+ func setProgressEventThrottle(_ throttleValue: NSNumber) {
578
+ progressEventThrottle.waitBetweenEvents = throttleValue.doubleValue
579
+ }
580
+
581
+
582
+ func shouldSendProgressEvent(progress: TileRegionLoadProgress, state: State) -> Bool
583
+ {
584
+ let currentTimestamp: Double = CACurrentMediaTime() * 1000.0
585
+
586
+ guard let lastSentState = progressEventThrottle.lastSentState, lastSentState == state else {
587
+ progressEventThrottle.lastSentState = state
588
+ progressEventThrottle.lastSentTimestamp = currentTimestamp
589
+ return true
590
+ }
591
+
592
+ guard let waitBetweenEvents = progressEventThrottle.waitBetweenEvents,
593
+ let lastSentTimestamp = progressEventThrottle.lastSentTimestamp else {
594
+ progressEventThrottle.lastSentTimestamp = currentTimestamp
595
+ return true;
596
+ }
597
+
598
+ if (currentTimestamp - lastSentTimestamp > waitBetweenEvents) {
599
+ progressEventThrottle.lastSentTimestamp = currentTimestamp
600
+ return true;
601
+ }
602
+
603
+ return false;
604
+ }
605
+ }
606
+
@@ -5,6 +5,10 @@ func deg2rad(_ number: Double) -> Double {
5
5
  return number * .pi / 180
6
6
  }
7
7
 
8
+ enum StyleConversionError: Error {
9
+ case unexpectedType(message: String)
10
+ }
11
+
8
12
  class RCTMGLStyleValue {
9
13
  var value: Any
10
14
  var styleType: String? = nil
@@ -325,11 +329,14 @@ class RCTMGLStyleValue {
325
329
  return .constant(valueObj)
326
330
  } else {
327
331
  do {
332
+ if valueObj is String {
333
+ throw StyleConversionError.unexpectedType(message: "should be array constant or expression")
334
+ }
328
335
  let data = try JSONSerialization.data(withJSONObject: valueObj, options: .prettyPrinted)
329
336
  let decodedExpression = try JSONDecoder().decode(Expression.self, from: data)
330
337
  return .expression(decodedExpression)
331
338
  } catch {
332
- Logger.log(level: .error, message: "Invalid value for array number: \(value) error: \(error) setting dummy value")
339
+ Logger.log(level: .error, message: "Invalid value for array => value: \(value) error: \(error) setting dummy value")
333
340
  return .constant([""])
334
341
  }
335
342
  }
@@ -0,0 +1,91 @@
1
+ import React from 'react';
2
+ import { NativeModules, requireNativeComponent } from 'react-native';
3
+
4
+ import {
5
+ FilterExpression,
6
+ BackgroundLayerStyleProps,
7
+ } from '../utils/MapboxStyles';
8
+ import { StyleValue } from '../utils/StyleValue';
9
+
10
+ import AbstractLayer from './AbstractLayer';
11
+
12
+ const MapboxGL = NativeModules.MGLModule;
13
+
14
+ export type Props = {
15
+ /**
16
+ * A string that uniquely identifies the source in the style to which it is added.
17
+ */
18
+ id: string;
19
+
20
+ /**
21
+ * The source from which to obtain the data to style.
22
+ * If the source has not yet been added to the current style, the behavior is undefined.
23
+ * Inferred from parent source only if the layer is a direct child to it.
24
+ */
25
+ sourceID?: string;
26
+
27
+ /**
28
+ * Identifier of the layer within the source identified by the sourceID property from which the receiver obtains the data to style.
29
+ */
30
+ sourceLayerID?: string;
31
+
32
+ /**
33
+ * Inserts a layer above aboveLayerID.
34
+ */
35
+ aboveLayerID?: string;
36
+
37
+ /**
38
+ * Inserts a layer below belowLayerID
39
+ */
40
+ belowLayerID?: string;
41
+
42
+ /**
43
+ * Inserts a layer at a specified index
44
+ */
45
+ layerIndex?: number;
46
+
47
+ /**
48
+ * Filter only the features in the source layer that satisfy a condition that you define
49
+ */
50
+ filter?: FilterExpression;
51
+
52
+ /**
53
+ * The minimum zoom level at which the layer gets parsed and appears.
54
+ */
55
+ minZoomLevel?: number;
56
+
57
+ /**
58
+ * The maximum zoom level at which the layer gets parsed and appears.
59
+ */
60
+ maxZoomLevel?: number;
61
+
62
+ /**
63
+ * Customizable style attributes
64
+ */
65
+ style?: BackgroundLayerStyleProps;
66
+ } & React.ComponentProps<typeof AbstractLayer>;
67
+
68
+ export const NATIVE_MODULE_NAME = 'RCTMGLBackgroundLayer';
69
+
70
+ type NativeTypeProps = Omit<Props, 'style'> & {
71
+ reactStyle?: { [key: string]: StyleValue };
72
+ };
73
+
74
+ class BackgroundLayer extends AbstractLayer<Props, NativeTypeProps> {
75
+ static defaultProps = {
76
+ sourceID: MapboxGL.StyleSource.DefaultSourceID,
77
+ };
78
+
79
+ render() {
80
+ const props = {
81
+ ...this.baseProps,
82
+ sourceLayerID: this.props.sourceLayerID,
83
+ };
84
+ return <RCTMGLBackgroundLayer ref={this.setNativeLayer} {...props} />;
85
+ }
86
+ }
87
+
88
+ const RCTMGLBackgroundLayer =
89
+ requireNativeComponent<NativeTypeProps>(NATIVE_MODULE_NAME);
90
+
91
+ export default BackgroundLayer;