@rnmapbox/maps 10.0.0-rc.5 → 10.0.0-rc.7
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/README.md +1 -1
- package/android/rctmgl/build.gradle +1 -1
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/camera/RCTMGLCamera.kt +2 -2
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/location/LocationComponentManager.kt +3 -2
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/mapview/RCTMGLMapView.kt +59 -17
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/mapview/RCTMGLMapViewManager.kt +8 -4
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/modules/RCTMGLModule.kt +4 -3
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/modules/RCTMGLOfflineModule.kt +474 -405
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/utils/extensions/FeatureCollection.kt +10 -0
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/utils/extensions/Geometry.kt +22 -0
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/utils/extensions/JSONObject.kt +78 -0
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/utils/extensions/ReadableArray.kt +1 -1
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/utils/extensions/Value.kt +9 -0
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/utils/writeableMapArrayOf.kt +41 -0
- package/ios/RCTMGL-v10/RCTMGLOfflineModule.swift +283 -307
- package/lib/commonjs/components/MapView.js +9 -0
- package/lib/commonjs/components/MapView.js.map +1 -1
- package/lib/commonjs/components/Terrain.js +1 -1
- package/lib/commonjs/components/VectorSource.js +2 -0
- package/lib/commonjs/components/VectorSource.js.map +1 -1
- package/lib/commonjs/modules/location/locationManager.js +4 -0
- package/lib/commonjs/modules/location/locationManager.js.map +1 -1
- package/lib/module/components/MapView.js +9 -0
- package/lib/module/components/MapView.js.map +1 -1
- package/lib/module/components/Terrain.js +1 -1
- package/lib/module/components/VectorSource.js +3 -0
- package/lib/module/components/VectorSource.js.map +1 -1
- package/lib/module/modules/location/locationManager.js +4 -0
- package/lib/module/modules/location/locationManager.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Terrain.tsx +1 -1
|
@@ -100,7 +100,7 @@ class RCTMGLOfflineModule: RCTEventEmitter {
|
|
|
100
100
|
var state : State = .inactive
|
|
101
101
|
var metadata : [String:Any]? = nil
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
// Stored in metadata for resume functionality:
|
|
104
104
|
var bounds: Geometry? = nil
|
|
105
105
|
var zoomRange: ClosedRange<UInt8>? = nil
|
|
106
106
|
var styleURI: StyleURI? = nil
|
|
@@ -133,7 +133,7 @@ class RCTMGLOfflineModule: RCTEventEmitter {
|
|
|
133
133
|
@objc
|
|
134
134
|
override
|
|
135
135
|
static func requiresMainQueueSetup() -> Bool {
|
|
136
|
-
|
|
136
|
+
return true
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
@objc
|
|
@@ -141,56 +141,254 @@ class RCTMGLOfflineModule: RCTEventEmitter {
|
|
|
141
141
|
func constantsToExport() -> [AnyHashable: Any]! {
|
|
142
142
|
return [:]
|
|
143
143
|
}
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
|
|
146
145
|
@objc
|
|
147
146
|
override
|
|
148
147
|
func supportedEvents() -> [String] {
|
|
149
148
|
return [Callbacks.error.rawValue, Callbacks.progress.rawValue]
|
|
150
149
|
}
|
|
151
150
|
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
// MARK: react methods
|
|
152
|
+
|
|
153
|
+
@objc
|
|
154
|
+
func createPack(_ options: NSDictionary, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
155
|
+
DispatchQueue.main.async {
|
|
156
|
+
do {
|
|
157
|
+
let metadataStr = options["metadata"] as! String
|
|
158
|
+
var metadata = try JSONSerialization.jsonObject(with: metadataStr.data(using: .utf8)!, options: []) as! [String:Any]
|
|
159
|
+
metadata["styleURI"] = options["styleURL"]
|
|
160
|
+
let id = metadata["name"] as! String
|
|
161
|
+
|
|
162
|
+
let boundsStr = options["bounds"] as! String
|
|
163
|
+
let boundsData = boundsStr.data(using: .utf8)
|
|
164
|
+
var boundsFC = try JSONDecoder().decode(FeatureCollection.self, from: boundsData!)
|
|
165
|
+
|
|
166
|
+
var bounds = self.convertPointPairToBounds(RCTMGLFeatureUtils.fcToGeomtry(boundsFC))
|
|
167
|
+
|
|
168
|
+
let actPack = RCTMGLOfflineModule.TileRegionPack(
|
|
169
|
+
name: id,
|
|
170
|
+
styleURI: StyleURI(rawValue: options["styleURL"] as! String)!,
|
|
171
|
+
bounds: bounds,
|
|
172
|
+
zoomRange: (options["minZoom"] as! NSNumber).uint8Value...(options["maxZoom"] as! NSNumber).uint8Value,
|
|
173
|
+
metadata: metadata
|
|
174
|
+
)
|
|
175
|
+
self.tileRegionPacks[id] = actPack
|
|
176
|
+
self.startLoading(pack: actPack)
|
|
177
|
+
|
|
178
|
+
resolver([
|
|
179
|
+
"bounds": boundsStr,
|
|
180
|
+
"metadata": String(data:try! JSONSerialization.data(withJSONObject: metadata, options: [.prettyPrinted]), encoding: .utf8)
|
|
181
|
+
])
|
|
182
|
+
} catch {
|
|
183
|
+
rejecter("createPack", error.localizedDescription, error)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@objc
|
|
189
|
+
func getPackStatus(_ name: String,
|
|
190
|
+
resolver: @escaping RCTPromiseResolveBlock,
|
|
191
|
+
rejecter: @escaping RCTPromiseRejectBlock) {
|
|
192
|
+
guard let pack = tileRegionPacks[name] else {
|
|
193
|
+
resolver(nil)
|
|
194
|
+
return
|
|
195
|
+
}
|
|
154
196
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
let
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
197
|
+
tileStore.tileRegionMetadata(forId: name) { result in
|
|
198
|
+
switch result {
|
|
199
|
+
case .failure(let error):
|
|
200
|
+
Logger.log(level:.error, message: "Unable to fetch metadata for \(name)")
|
|
201
|
+
rejecter("RCTMGLOfflineModule.getPackStatus", error.localizedDescription, error)
|
|
202
|
+
case .success(let metadata):
|
|
203
|
+
var pack = self.tileRegionPacks[name] ?? TileRegionPack(
|
|
204
|
+
name: name,
|
|
205
|
+
metadata: logged("RCTMGLOfflineModule.getPackStatus") { metadata as? [String:Any] } ?? [:]
|
|
206
|
+
)
|
|
207
|
+
self.tileRegionPacks[name] = pack
|
|
208
|
+
resolver(self._makeRegionStatusPayload(pack: pack))
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@objc
|
|
214
|
+
func resumePackDownload(_ name: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock)
|
|
215
|
+
{
|
|
216
|
+
if let pack = tileRegionPacks[name] {
|
|
217
|
+
startLoading(pack: pack)
|
|
218
|
+
resolver(nil)
|
|
219
|
+
} else {
|
|
220
|
+
rejecter("resumePackDownload", "Unknown offline pack: \(name)", nil)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@objc
|
|
225
|
+
func pausePackDownload(_ name: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock)
|
|
226
|
+
{
|
|
227
|
+
if let pack = tileRegionPacks[name] {
|
|
228
|
+
if let cancelable = pack.cancelable {
|
|
229
|
+
cancelable.cancel()
|
|
230
|
+
tileRegionPacks[name]?.cancelable = nil
|
|
231
|
+
resolver(nil)
|
|
175
232
|
} else {
|
|
176
|
-
|
|
233
|
+
rejecter("pausePackDownload", "Offline pack: \(name) already cancelled", nil)
|
|
177
234
|
}
|
|
178
|
-
|
|
179
|
-
|
|
235
|
+
} else {
|
|
236
|
+
rejecter("pausePackDownload", "Unknown offline region: \(name)", nil)
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
@objc
|
|
241
|
+
func setTileCountLimit(_ limit: NSNumber) {
|
|
242
|
+
self.offlineRegionManager.setOfflineMapboxTileCountLimitForLimit(limit.uint64Value)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@objc
|
|
247
|
+
func deletePack(_ name: String,
|
|
248
|
+
resolver: RCTPromiseResolveBlock,
|
|
249
|
+
rejecter: RCTPromiseRejectBlock)
|
|
250
|
+
{
|
|
251
|
+
guard let pack = tileRegionPacks[name] else {
|
|
252
|
+
return resolver(nil)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
guard pack.state != .invalid else {
|
|
256
|
+
return rejecter("deletePack", "Pack: \(name) has already been deleted", nil)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
tileStore.removeTileRegion(forId: name)
|
|
260
|
+
tileRegionPacks[name]!.state = .invalid
|
|
261
|
+
resolver(nil)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@objc
|
|
265
|
+
func migrateOfflineCache(_ resolve : @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
266
|
+
// Old and new cache file paths
|
|
267
|
+
let srcURL = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("/Library/Application Support/com.mapbox.examples/.mapbox/cache.db")
|
|
268
|
+
|
|
269
|
+
let destURL = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("/Library/Application Support/.mapbox/map_data/map_data.db")
|
|
270
|
+
|
|
271
|
+
let fileManager = FileManager.default
|
|
272
|
+
|
|
273
|
+
do {
|
|
274
|
+
try fileManager.createDirectory(at: destURL.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil)
|
|
275
|
+
try fileManager.moveItem(at: srcURL, to: destURL)
|
|
276
|
+
resolve(nil)
|
|
277
|
+
} catch {
|
|
278
|
+
reject("migrateOfflineCache", error.localizedDescription, error)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@objc
|
|
283
|
+
func resetDatabase(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
284
|
+
self.tileStore.allTileRegions { result in
|
|
285
|
+
switch result {
|
|
286
|
+
case .success(let regions):
|
|
287
|
+
regions.forEach { region in
|
|
288
|
+
self.tileStore.removeTileRegion(forId: region.id)
|
|
289
|
+
}
|
|
290
|
+
self.offlineManager.allStylePacks { result in
|
|
291
|
+
switch result {
|
|
292
|
+
case .success(let packs):
|
|
293
|
+
packs.forEach { pack in
|
|
294
|
+
if let url = logged("RCTMGLOfflineModule.resetDatabase invalid styleURI",fn: { return URL(string: pack.styleURI) }),
|
|
295
|
+
let styleUri = logged("RCTMGLOfflineModule.resetDatabase invalid styleURI2", fn: { return StyleURI(url: url) }) {
|
|
296
|
+
self.offlineManager.removeStylePack(for: styleUri)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
resolve(nil)
|
|
300
|
+
case .failure(let error):
|
|
301
|
+
Logger.log(level:.error, message: "RCTMGLOfflineModule.resetDatabase/allStylePacks \(error.localizedDescription) \(error)")
|
|
302
|
+
reject("RCTMGLOfflineModule.resetDatabase/allStylePacks", error.localizedDescription, error)
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
case .failure(let error):
|
|
306
|
+
Logger.log(level:.error, message: "RCTMGLOfflineModule.resetDatabase/allTileRegions \(error.localizedDescription) \(error)")
|
|
307
|
+
reject("RCTMGLOfflineModule.resetDatabase/allTileRegions", error.localizedDescription, error)
|
|
180
308
|
}
|
|
181
|
-
|
|
182
|
-
result["metadata"] = String(data:try! JSONSerialization.data(withJSONObject: metadata, options: [.prettyPrinted]), encoding: .utf8)
|
|
183
|
-
|
|
184
|
-
result["bounds"] = jsonBounds
|
|
185
309
|
}
|
|
186
|
-
return result
|
|
187
310
|
}
|
|
188
311
|
|
|
189
|
-
|
|
190
|
-
|
|
312
|
+
@objc
|
|
313
|
+
func getPacks(_ resolve : @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
314
|
+
DispatchQueue.main.async {
|
|
315
|
+
self.tileStore.allTileRegions { result in
|
|
316
|
+
switch result {
|
|
317
|
+
case .success(let regions):
|
|
318
|
+
self.convertRegionsToJSON(regions: regions, resolve: resolve, rejecter: rejecter)
|
|
319
|
+
case .failure(let error):
|
|
320
|
+
rejecter("TileStoreError", error.localizedDescription, error)
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
func startLoading(pack: TileRegionPack) {
|
|
327
|
+
let id = pack.name
|
|
328
|
+
guard let bounds = pack.bounds else {
|
|
329
|
+
RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there are no bounds in pack")
|
|
330
|
+
return
|
|
331
|
+
}
|
|
332
|
+
guard let zoomRange = pack.zoomRange else {
|
|
333
|
+
RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there is no zoom range in pack")
|
|
334
|
+
return
|
|
335
|
+
}
|
|
336
|
+
guard let styleURI = pack.styleURI else {
|
|
337
|
+
RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there is no styleURI in pack")
|
|
338
|
+
return
|
|
339
|
+
}
|
|
340
|
+
guard let metadata = pack.metadata else {
|
|
341
|
+
RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there is no metadata in pack")
|
|
342
|
+
return
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
let stylePackLoadOptions = StylePackLoadOptions(glyphsRasterizationMode: .ideographsRasterizedLocally, metadata: pack.metadata)
|
|
346
|
+
|
|
347
|
+
let descriptorOptions = TilesetDescriptorOptions(
|
|
348
|
+
styleURI: styleURI,
|
|
349
|
+
zoomRange: zoomRange,
|
|
350
|
+
stylePackOptions: stylePackLoadOptions
|
|
351
|
+
)
|
|
352
|
+
let tilesetDescriptor = self.offlineManager.createTilesetDescriptor(for: descriptorOptions)
|
|
353
|
+
|
|
354
|
+
let loadOptions = TileRegionLoadOptions(
|
|
355
|
+
geometry: bounds, // RCTMGLFeatureUtils.geometryToGeometry(bounds),
|
|
356
|
+
descriptors: [tilesetDescriptor],
|
|
357
|
+
metadata: metadata,
|
|
358
|
+
acceptExpired: true,
|
|
359
|
+
networkRestriction: .none,
|
|
360
|
+
averageBytesPerSecond: nil)
|
|
361
|
+
|
|
362
|
+
var lastProgress : TileRegionLoadProgress? = nil
|
|
363
|
+
let task = self.tileStore.loadTileRegion(forId: id, loadOptions: loadOptions!, progress: {
|
|
364
|
+
progress in
|
|
365
|
+
lastProgress = progress
|
|
366
|
+
self.tileRegionPacks[id]!.progress = progress
|
|
367
|
+
self.tileRegionPacks[id]!.state = .active
|
|
368
|
+
self.offlinePackProgressDidChange(progress: progress, metadata: metadata, state: .active)
|
|
369
|
+
}) { result in
|
|
370
|
+
switch result {
|
|
371
|
+
case .success(let _):
|
|
372
|
+
DispatchQueue.main.async {
|
|
373
|
+
if let progess = lastProgress {
|
|
374
|
+
self.offlinePackProgressDidChange(progress: progess, metadata: metadata, state: .complete)
|
|
375
|
+
} else {
|
|
376
|
+
Logger.log(level: .warn,
|
|
377
|
+
message: "RCTMGLOfflineModule: startLoading: tile region completed, but got no progress information")
|
|
378
|
+
}
|
|
379
|
+
self.tileRegionPacks[id]!.state = .complete
|
|
380
|
+
}
|
|
381
|
+
case .failure(let error):
|
|
382
|
+
DispatchQueue.main.async {
|
|
383
|
+
self.tileRegionPacks[id]!.state = .inactive
|
|
384
|
+
self.offlinePackDidReceiveError(name: id, error: error)
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
self.tileRegionPacks[id]!.cancelable = task
|
|
191
389
|
}
|
|
192
390
|
|
|
193
|
-
func
|
|
391
|
+
func convertRegionsToJSON(regions: [TileRegion], resolve: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
194
392
|
let taskGroup = DispatchGroup()
|
|
195
393
|
|
|
196
394
|
var geomteryResults : [String: (Result<Geometry,Error>,TileRegion)] = [:]
|
|
@@ -219,21 +417,21 @@ class RCTMGLOfflineModule: RCTEventEmitter {
|
|
|
219
417
|
return false
|
|
220
418
|
}
|
|
221
419
|
}
|
|
222
|
-
|
|
420
|
+
|
|
223
421
|
if let firstError = firstError {
|
|
224
422
|
switch firstError.value.0 {
|
|
225
423
|
case .failure(let error):
|
|
226
|
-
rejecter("
|
|
424
|
+
rejecter("convertRegionsToJSON", error.localizedDescription, error)
|
|
227
425
|
return
|
|
228
426
|
case .success:
|
|
229
|
-
fatalError("Expected failure but was success")
|
|
427
|
+
fatalError("convertRegionsToJson:Expected failure but was success")
|
|
230
428
|
}
|
|
231
429
|
}
|
|
232
|
-
|
|
430
|
+
|
|
233
431
|
let results = geomteryResults.map { (id, result) -> (String, (Geometry,TileRegion, [String:Any]?)) in
|
|
234
432
|
switch result.0 {
|
|
235
433
|
case .failure(_):
|
|
236
|
-
fatalError("Expected
|
|
434
|
+
fatalError("convertRegionsToJson:Expected success but was failure")
|
|
237
435
|
case .success(let geometry):
|
|
238
436
|
return (id, (geometry,result.1,(try? metadataResults[id]?.get()) as? [String:Any]))
|
|
239
437
|
}
|
|
@@ -248,60 +446,59 @@ class RCTMGLOfflineModule: RCTEventEmitter {
|
|
|
248
446
|
progress: self.toProgress(region: region),
|
|
249
447
|
metadata: logged("RCTMGLOfflineModule.getPacks metadata is null") { metadata } ?? [:]
|
|
250
448
|
)
|
|
251
|
-
|
|
252
|
-
if ((region.completedResourceCount == region.
|
|
449
|
+
|
|
450
|
+
if ((region.completedResourceCount == region.requiredResourceCount)) {
|
|
253
451
|
pack.state = .complete
|
|
254
452
|
}
|
|
255
|
-
|
|
453
|
+
|
|
256
454
|
self.tileRegionPacks[region.id] = pack
|
|
257
|
-
|
|
455
|
+
|
|
258
456
|
return ret
|
|
259
457
|
})
|
|
260
458
|
}
|
|
261
459
|
}
|
|
262
460
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
461
|
+
func convertRegionToJSON(region: TileRegion, geometry: Geometry, metadata: [String:Any]?) -> [String:Any] {
|
|
462
|
+
let bb = RCTMGLFeatureUtils.boundingBox(geometry: geometry)
|
|
463
|
+
|
|
464
|
+
if let bb = bb {
|
|
465
|
+
let jsonBounds = [
|
|
466
|
+
bb.northEast.longitude, bb.northEast.latitude,
|
|
467
|
+
bb.southWest.longitude, bb.southWest.latitude
|
|
468
|
+
]
|
|
469
|
+
|
|
470
|
+
let completed = (region.completedResourceCount == region.requiredResourceCount)
|
|
471
|
+
|
|
472
|
+
var metadata : [String:Any] = metadata ?? [:]
|
|
473
|
+
metadata["name"] = region.id
|
|
474
|
+
|
|
475
|
+
var result : [String:Any] = [
|
|
476
|
+
"requiredResourceCount": region.requiredResourceCount,
|
|
477
|
+
"completedResourceCount": region.completedResourceCount,
|
|
478
|
+
"completedResourceSize": region.completedResourceSize,
|
|
479
|
+
"state": completed ? State.complete.rawValue : State.unknown.rawValue,
|
|
480
|
+
"metadata": String(data:try! JSONSerialization.data(withJSONObject: metadata, options: [.prettyPrinted]), encoding: .utf8),
|
|
481
|
+
"bounds": jsonBounds
|
|
482
|
+
]
|
|
483
|
+
|
|
484
|
+
if region.requiredResourceCount > 0 {
|
|
485
|
+
let percentage = Float(100.0) * Float(region.completedResourceCount) / Float(region.requiredResourceCount)
|
|
486
|
+
result["percentage"] = percentage
|
|
487
|
+
} else {
|
|
488
|
+
result["percentage"] = nil
|
|
489
|
+
}
|
|
490
|
+
if let expires = region.expires {
|
|
491
|
+
result["expires"] = expires.toJSONString()
|
|
275
492
|
}
|
|
276
493
|
|
|
277
|
-
/*
|
|
278
|
-
self.offlineManager.allStylePacks { (result) in
|
|
279
|
-
switch result {
|
|
280
|
-
case .success(let packs):
|
|
281
|
-
resolve(self.convertPacksToJson(packs: packs))
|
|
282
|
-
case .failure(let error):
|
|
283
|
-
rejecter(error.localizedDescription, error.localizedDescription, error)
|
|
284
|
-
}
|
|
285
|
-
}*/
|
|
286
494
|
}
|
|
495
|
+
return [:]
|
|
496
|
+
}
|
|
287
497
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
// dispatch_async(dispatch_get_main_queue(), ^{
|
|
291
|
-
/*
|
|
292
|
-
NSArray<MGLOfflinePack *> *packs = [[MGLOfflineStorage sharedOfflineStorage] packs];
|
|
293
|
-
|
|
294
|
-
if (packs == nil) {
|
|
295
|
-
// packs have not loaded yet
|
|
296
|
-
[self->packRequestQueue addObject:resolve];
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
resolve([self _convertPacksToJson:packs]);
|
|
301
|
-
});*/
|
|
498
|
+
func toProgress(region: TileRegion) -> TileRegionLoadProgress? {
|
|
499
|
+
return TileRegionLoadProgress(completedResourceCount: region.completedResourceCount, completedResourceSize: region.completedResourceSize, erroredResourceCount: 0, requiredResourceCount: region.requiredResourceCount, loadedResourceCount: 0, loadedResourceSize: 0)
|
|
302
500
|
}
|
|
303
501
|
|
|
304
|
-
|
|
305
502
|
func convertPointPairToBounds(_ bounds: Geometry) -> Geometry {
|
|
306
503
|
guard case .geometryCollection(let gc) = bounds else {
|
|
307
504
|
return bounds
|
|
@@ -320,10 +517,10 @@ class RCTMGLOfflineModule: RCTEventEmitter {
|
|
|
320
517
|
let pt1 = g1.coordinates
|
|
321
518
|
return .polygon(Polygon([
|
|
322
519
|
[
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
520
|
+
pt0,
|
|
521
|
+
CLLocationCoordinate2D(latitude: pt0.latitude, longitude: pt1.longitude),
|
|
522
|
+
pt1,
|
|
523
|
+
CLLocationCoordinate2D(latitude: pt1.latitude, longitude: pt0.longitude)
|
|
327
524
|
]
|
|
328
525
|
]))
|
|
329
526
|
}
|
|
@@ -383,228 +580,7 @@ class RCTMGLOfflineModule: RCTEventEmitter {
|
|
|
383
580
|
let event = RCTMGLEvent(type: .offlineError, payload: ["name": name, "message": error.localizedDescription])
|
|
384
581
|
self._sendEvent(Callbacks.error.rawValue, event: event)
|
|
385
582
|
}
|
|
386
|
-
|
|
387
|
-
@objc
|
|
388
|
-
func createPack(_ options: NSDictionary, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
389
|
-
DispatchQueue.main.async {
|
|
390
|
-
do {
|
|
391
|
-
let metadataStr = options["metadata"] as! String
|
|
392
|
-
var metadata = try JSONSerialization.jsonObject(with: metadataStr.data(using: .utf8)!, options: []) as! [String:Any]
|
|
393
|
-
metadata["styleURI"] = options["styleURL"]
|
|
394
|
-
let id = metadata["name"] as! String
|
|
395
|
-
|
|
396
|
-
let boundsStr = options["bounds"] as! String
|
|
397
|
-
let boundsData = boundsStr.data(using: .utf8)
|
|
398
|
-
var boundsFC = try JSONDecoder().decode(FeatureCollection.self, from: boundsData!)
|
|
399
|
-
|
|
400
|
-
var bounds = self.convertPointPairToBounds(RCTMGLFeatureUtils.fcToGeomtry(boundsFC))
|
|
401
|
-
|
|
402
|
-
let actPack = RCTMGLOfflineModule.TileRegionPack(
|
|
403
|
-
name: id,
|
|
404
|
-
styleURI: StyleURI(rawValue: options["styleURL"] as! String)!,
|
|
405
|
-
bounds: bounds,
|
|
406
|
-
zoomRange: (options["minZoom"] as! NSNumber).uint8Value...(options["maxZoom"] as! NSNumber).uint8Value,
|
|
407
|
-
metadata: metadata
|
|
408
|
-
)
|
|
409
|
-
self.tileRegionPacks[id] = actPack
|
|
410
|
-
self.startLoading(pack: actPack)
|
|
411
|
-
|
|
412
|
-
resolver([
|
|
413
|
-
"bounds": boundsStr,
|
|
414
|
-
"metadata": String(data:try! JSONSerialization.data(withJSONObject: metadata, options: [.prettyPrinted]), encoding: .utf8)
|
|
415
|
-
])
|
|
416
|
-
} catch {
|
|
417
|
-
rejecter("createPack", error.localizedDescription, error)
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
func startLoading(pack: TileRegionPack) {
|
|
423
|
-
let id = pack.name
|
|
424
|
-
guard let bounds = pack.bounds else {
|
|
425
|
-
RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there are no bounds in pack")
|
|
426
|
-
return
|
|
427
|
-
}
|
|
428
|
-
guard let zoomRange = pack.zoomRange else {
|
|
429
|
-
RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there is no zoom range in pack")
|
|
430
|
-
return
|
|
431
|
-
}
|
|
432
|
-
guard let styleURI = pack.styleURI else {
|
|
433
|
-
RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there is no styleURI in pack")
|
|
434
|
-
return
|
|
435
|
-
}
|
|
436
|
-
guard let metadata = pack.metadata else {
|
|
437
|
-
RCTMGLLogError("RCTMGLOfflineModule.startLoading failed as there is no metadata in pack")
|
|
438
|
-
return
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
let stylePackLoadOptions = StylePackLoadOptions(glyphsRasterizationMode: .ideographsRasterizedLocally, metadata: pack.metadata)
|
|
442
|
-
|
|
443
|
-
let descriptorOptions = TilesetDescriptorOptions(
|
|
444
|
-
styleURI: styleURI,
|
|
445
|
-
zoomRange: zoomRange,
|
|
446
|
-
stylePackOptions: stylePackLoadOptions
|
|
447
|
-
)
|
|
448
|
-
let tilesetDescriptor = self.offlineManager.createTilesetDescriptor(for: descriptorOptions)
|
|
449
|
-
|
|
450
|
-
let loadOptions = TileRegionLoadOptions(
|
|
451
|
-
geometry: bounds, // RCTMGLFeatureUtils.geometryToGeometry(bounds),
|
|
452
|
-
descriptors: [tilesetDescriptor],
|
|
453
|
-
metadata: metadata,
|
|
454
|
-
acceptExpired: true,
|
|
455
|
-
networkRestriction: .none,
|
|
456
|
-
averageBytesPerSecond: nil)
|
|
457
|
-
|
|
458
|
-
var lastProgress : TileRegionLoadProgress? = nil
|
|
459
|
-
let task = self.tileStore.loadTileRegion(forId: id, loadOptions: loadOptions!, progress: {
|
|
460
|
-
progress in
|
|
461
|
-
lastProgress = progress
|
|
462
|
-
self.tileRegionPacks[id]!.progress = progress
|
|
463
|
-
self.tileRegionPacks[id]!.state = .active
|
|
464
|
-
self.offlinePackProgressDidChange(progress: progress, metadata: metadata, state: .active)
|
|
465
|
-
}) { result in
|
|
466
|
-
switch result {
|
|
467
|
-
case .success(let value):
|
|
468
|
-
DispatchQueue.main.async {
|
|
469
|
-
if let progess = lastProgress {
|
|
470
|
-
self.offlinePackProgressDidChange(progress: progess, metadata: metadata, state: .complete)
|
|
471
|
-
}
|
|
472
|
-
self.tileRegionPacks[id]!.state = .complete
|
|
473
|
-
}
|
|
474
|
-
case .failure(let error):
|
|
475
|
-
DispatchQueue.main.async {
|
|
476
|
-
self.tileRegionPacks[id]!.state = .inactive
|
|
477
|
-
self.offlinePackDidReceiveError(name: id, error: error)
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
self.tileRegionPacks[id]!.cancelable = task
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
func _getPack(fromName: String) -> TileRegionPack? {
|
|
485
|
-
return self.tileRegionPacks[fromName]
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
@objc
|
|
489
|
-
func getPackStatus(_ name: String,
|
|
490
|
-
resolver: @escaping RCTPromiseResolveBlock,
|
|
491
|
-
rejecter: @escaping RCTPromiseRejectBlock) {
|
|
492
|
-
guard let pack = self._getPack(fromName: name) else {
|
|
493
|
-
resolver(nil)
|
|
494
|
-
return
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
tileStore.tileRegionMetadata(forId: name) { result in
|
|
498
|
-
switch result {
|
|
499
|
-
case .failure(let error):
|
|
500
|
-
Logger.log(level:.error, message: "Unable to fetch metadata for \(name)")
|
|
501
|
-
rejecter("RCTMGLOfflineModule.getPackStatus", error.localizedDescription, error)
|
|
502
|
-
case .success(let metadata):
|
|
503
|
-
var pack = self.tileRegionPacks[name] ?? TileRegionPack(
|
|
504
|
-
name: name,
|
|
505
|
-
metadata: logged("RCTMGLOfflineModule.getPackStatus") { metadata as? [String:Any] } ?? [:]
|
|
506
|
-
)
|
|
507
|
-
self.tileRegionPacks[name] = pack
|
|
508
|
-
resolver(self._makeRegionStatusPayload(pack: pack))
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
@objc
|
|
515
|
-
func resumePackDownload(_ name: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock)
|
|
516
|
-
{
|
|
517
|
-
if let pack = _getPack(fromName: name) {
|
|
518
|
-
self.startLoading(pack: pack)
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
@objc
|
|
523
|
-
func pausePackDownload(_ name: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock)
|
|
524
|
-
{
|
|
525
|
-
if let pack = _getPack(fromName: name) {
|
|
526
|
-
pack.cancelable?.cancel()
|
|
527
|
-
resolver(nil)
|
|
528
|
-
} else {
|
|
529
|
-
rejecter("pausePackDownload", "Unknown offline region: \(name)", nil)
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
@objc
|
|
534
|
-
func setTileCountLimit(_ limit: NSNumber) {
|
|
535
|
-
self.offlineRegionManager.setOfflineMapboxTileCountLimitForLimit(limit.uint64Value)
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
@objc
|
|
540
|
-
func deletePack(_ name: String,
|
|
541
|
-
resolver: RCTPromiseResolveBlock,
|
|
542
|
-
rejecter: RCTPromiseRejectBlock)
|
|
543
|
-
{
|
|
544
|
-
guard let pack = _getPack(fromName: name) else {
|
|
545
|
-
return resolver(nil)
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
guard pack.state != .invalid else {
|
|
549
|
-
let error = NSError(domain:"RCTMGLErororDomain", code: 1, userInfo: [NSLocalizedDescriptionKey: "Pack has already beend deleted"])
|
|
550
|
-
return rejecter("deletePack", error.description, error)
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
self.tileStore.removeTileRegion(forId: name)
|
|
554
|
-
self.tileRegionPacks[name]!.state = .invalid
|
|
555
|
-
resolver(nil)
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
@objc
|
|
559
|
-
func migrateOfflineCache(_ resolve : @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
560
|
-
// Old and new cache file paths
|
|
561
|
-
let srcURL = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("/Library/Application Support/com.mapbox.examples/.mapbox/cache.db")
|
|
562
|
-
|
|
563
|
-
let destURL = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("/Library/Application Support/.mapbox/map_data/map_data.db")
|
|
564
|
-
|
|
565
|
-
let fileManager = FileManager.default
|
|
566
|
-
|
|
567
|
-
do {
|
|
568
|
-
try fileManager.createDirectory(at: destURL.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil)
|
|
569
|
-
try fileManager.moveItem(at: srcURL, to: destURL)
|
|
570
|
-
resolve(nil)
|
|
571
|
-
} catch {
|
|
572
|
-
reject("migrateOfflineCache", error.localizedDescription, error)
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
@objc
|
|
577
|
-
func resetDatabase(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
578
|
-
self.tileStore.allTileRegions { result in
|
|
579
|
-
switch result {
|
|
580
|
-
case .success(let regions):
|
|
581
|
-
regions.forEach { region in
|
|
582
|
-
self.tileStore.removeTileRegion(forId: region.id)
|
|
583
|
-
}
|
|
584
|
-
self.offlineManager.allStylePacks { result in
|
|
585
|
-
switch result {
|
|
586
|
-
case .success(let packs):
|
|
587
|
-
packs.forEach { pack in
|
|
588
|
-
if let url = logged("RCTMGLOfflineModule.resetDatabase invalid styleURI",fn: { return URL(string: pack.styleURI) }),
|
|
589
|
-
let styleUri = logged("RCTMGLOfflineModule.resetDatabase invalid styleURI2", fn: { return StyleURI(url: url) }) {
|
|
590
|
-
self.offlineManager.removeStylePack(for: styleUri)
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
resolve(nil)
|
|
594
|
-
case .failure(let error):
|
|
595
|
-
Logger.log(level:.error, message: "RCTMGLOfflineModule.resetDatabase/allStylePacks \(error.localizedDescription) \(error)")
|
|
596
|
-
reject("RCTMGLOfflineModule.resetDatabase/allStylePacks", error.localizedDescription, error)
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
case .failure(let error):
|
|
600
|
-
Logger.log(level:.error, message: "RCTMGLOfflineModule.resetDatabase/allTileRegions \(error.localizedDescription) \(error)")
|
|
601
|
-
reject("RCTMGLOfflineModule.resetDatabase/allTileRegions", error.localizedDescription, error)
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
583
|
}
|
|
607
|
-
|
|
608
584
|
// MARK: progress throttle
|
|
609
585
|
|
|
610
586
|
extension RCTMGLOfflineModule {
|
|
@@ -35,6 +35,15 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
const defaultStyleURL = MGLModule.StyleURL.Street;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* v10 only
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* label localization settings (v10 only). `true` is equivalent to current locale.
|
|
45
|
+
*/
|
|
46
|
+
|
|
38
47
|
/**
|
|
39
48
|
* MapView backed by Mapbox Native GL
|
|
40
49
|
*/
|