@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
|
@@ -1,49 +1,92 @@
|
|
|
1
1
|
package com.mapbox.rctmgl.modules
|
|
2
2
|
|
|
3
|
+
import android.R.array
|
|
4
|
+
import android.os.Build
|
|
3
5
|
import android.util.Log
|
|
4
6
|
import com.facebook.react.bridge.*
|
|
5
7
|
import com.facebook.react.module.annotations.ReactModule
|
|
6
|
-
import com.mapbox.rctmgl.modules.RCTMGLOfflineModule
|
|
7
|
-
import com.mapbox.rctmgl.modules.TileRegionPack
|
|
8
|
-
import com.mapbox.maps.OfflineManager
|
|
9
|
-
import com.mapbox.rctmgl.utils.LatLngBounds
|
|
10
|
-
import com.mapbox.maps.TilesetDescriptorOptions
|
|
11
|
-
import com.mapbox.rctmgl.utils.GeoJSONUtils
|
|
12
|
-
import com.mapbox.bindgen.Expected
|
|
13
|
-
import com.mapbox.geojson.Geometry
|
|
14
|
-
import com.mapbox.rctmgl.events.IEvent
|
|
15
8
|
import com.facebook.react.modules.core.RCTNativeAppEventEmitter
|
|
9
|
+
import com.mapbox.bindgen.Expected
|
|
16
10
|
import com.mapbox.bindgen.Value
|
|
17
|
-
import com.mapbox.rctmgl.events.OfflineEvent
|
|
18
11
|
import com.mapbox.common.*
|
|
12
|
+
import com.mapbox.geojson.*
|
|
13
|
+
import com.mapbox.maps.*
|
|
14
|
+
import com.mapbox.rctmgl.events.IEvent
|
|
15
|
+
import com.mapbox.rctmgl.events.OfflineEvent
|
|
19
16
|
import com.mapbox.rctmgl.events.constants.EventTypes
|
|
20
|
-
import com.mapbox.
|
|
21
|
-
import com.mapbox.maps.OfflineRegionManager
|
|
22
|
-
import com.mapbox.turf.TurfMeasurement
|
|
23
|
-
import com.mapbox.maps.ResourceOptions
|
|
24
|
-
import com.mapbox.rctmgl.modules.RCTMGLModule
|
|
25
|
-
import com.mapbox.rctmgl.utils.ConvertUtils
|
|
17
|
+
import com.mapbox.rctmgl.utils.*
|
|
26
18
|
import com.mapbox.rctmgl.utils.Logger
|
|
19
|
+
import com.mapbox.rctmgl.utils.extensions.*
|
|
20
|
+
import com.mapbox.turf.TurfMeasurement
|
|
21
|
+
import org.json.JSONArray
|
|
27
22
|
import org.json.JSONException
|
|
28
23
|
import org.json.JSONObject
|
|
29
24
|
import java.io.File
|
|
30
25
|
import java.io.UnsupportedEncodingException
|
|
31
|
-
import java.lang.Error
|
|
32
26
|
import java.nio.file.Files
|
|
33
27
|
import java.nio.file.Paths
|
|
34
28
|
import java.nio.file.StandardCopyOption
|
|
35
|
-
import java.util.ArrayList
|
|
36
|
-
import java.util.HashMap
|
|
37
29
|
import java.util.concurrent.CountDownLatch
|
|
38
30
|
|
|
39
|
-
class
|
|
31
|
+
data class ZoomRange(val minZoom: Byte, val maxZoom: Byte) {
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const val RNMapboxInfoMetadataKey = "_rnmapbox"
|
|
36
|
+
|
|
37
|
+
enum class TileRegionPackState(val rawValue: String) {
|
|
38
|
+
INVALID("invalid"),
|
|
39
|
+
INACTIVE("inactive"),
|
|
40
|
+
ACTIVE("active"),
|
|
41
|
+
COMPLETE("complete"),
|
|
42
|
+
UNKNOWN("unkown")
|
|
43
|
+
}
|
|
44
|
+
class TileRegionPack(var name: String, var progress: TileRegionLoadProgress?, var state: TileRegionPackState, var metadata: JSONObject) {
|
|
40
45
|
var cancelable: Cancelable? = null
|
|
41
46
|
var loadOptions: TileRegionLoadOptions? = null
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
// stored in metadata for resume functionality
|
|
49
|
+
var styleURI: String? = null
|
|
50
|
+
var bounds: Geometry? = null
|
|
51
|
+
var zoomRange: ZoomRange? = null
|
|
52
|
+
|
|
53
|
+
init {
|
|
54
|
+
val rnMetadata = metadata.optJSONObject(RNMapboxInfoMetadataKey)
|
|
55
|
+
if (rnMetadata != null) {
|
|
56
|
+
val styleURI = rnMetadata.optString("styleURI")
|
|
57
|
+
if (styleURI != null) {
|
|
58
|
+
this.styleURI = styleURI
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
val bounds = rnMetadata.optJSONObject("bounds")
|
|
62
|
+
if (bounds != null) {
|
|
63
|
+
this.bounds = bounds.toGeometry()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
val zoomRange = rnMetadata.optJSONArray("zoomRange")
|
|
67
|
+
if (zoomRange != null) {
|
|
68
|
+
this.zoomRange =
|
|
69
|
+
ZoomRange(zoomRange.getInt(0).toByte(), zoomRange.getInt(1).toByte())
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public constructor(
|
|
75
|
+
name: String,
|
|
76
|
+
state: TileRegionPackState = TileRegionPackState.UNKNOWN,
|
|
77
|
+
styleURI: String,
|
|
78
|
+
bounds: Geometry,
|
|
79
|
+
zoomRange: ZoomRange,
|
|
80
|
+
metadata: JSONObject
|
|
81
|
+
) : this(name, null, state, metadata) {
|
|
82
|
+
val rnmeta = JSONObject()
|
|
83
|
+
rnmeta.put("styleURI", styleURI)
|
|
84
|
+
this.styleURI = styleURI
|
|
85
|
+
rnmeta.put("bounds", bounds.toJSONObject())
|
|
86
|
+
this.bounds = bounds
|
|
87
|
+
rnmeta.put("zoomRange", JSONArray(arrayOf(zoomRange.minZoom, zoomRange.maxZoom)))
|
|
88
|
+
this.zoomRange = zoomRange
|
|
89
|
+
this.metadata.put(RNMapboxInfoMetadataKey, rnmeta);
|
|
47
90
|
}
|
|
48
91
|
}
|
|
49
92
|
|
|
@@ -54,6 +97,21 @@ class RCTMGLOfflineModule(private val mReactContext: ReactApplicationContext) :
|
|
|
54
97
|
) {
|
|
55
98
|
var tileRegionPacks = HashMap<String, TileRegionPack>()
|
|
56
99
|
private var mProgressEventThrottle = 300.0
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
val tileStore: TileStore by lazy {
|
|
103
|
+
TileStore.create()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
val offlineManager: OfflineManager by lazy {
|
|
107
|
+
OfflineManager(
|
|
108
|
+
ResourceOptions.Builder()
|
|
109
|
+
.accessToken(RCTMGLModule.getAccessToken(mReactContext)).tileStore(
|
|
110
|
+
tileStore
|
|
111
|
+
).build()
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
57
115
|
override fun getName(): String {
|
|
58
116
|
return REACT_CLASS
|
|
59
117
|
}
|
|
@@ -68,52 +126,401 @@ class RCTMGLOfflineModule(private val mReactContext: ReactApplicationContext) :
|
|
|
68
126
|
// Remove upstream listeners, stop unnecessary background tasks
|
|
69
127
|
}
|
|
70
128
|
|
|
129
|
+
// region React methods
|
|
71
130
|
@ReactMethod
|
|
72
131
|
@Throws(JSONException::class)
|
|
73
132
|
fun createPack(options: ReadableMap, promise: Promise) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
133
|
+
try {
|
|
134
|
+
val metadataStr = options.getString("metadata")!!
|
|
135
|
+
val metadata = JSONObject(metadataStr)
|
|
136
|
+
val metadataValue = Value.valueOf(metadataStr)
|
|
137
|
+
val id = metadata.getString("name")!!
|
|
138
|
+
|
|
139
|
+
val boundsStr = options.getString("bounds")!!
|
|
140
|
+
val boundsFC = FeatureCollection.fromJson(boundsStr)
|
|
141
|
+
val bounds = convertPointPairToBounds(boundsFC)
|
|
142
|
+
|
|
143
|
+
val actPack = TileRegionPack(
|
|
144
|
+
name = id,
|
|
145
|
+
styleURI = options.getString("styleURL")!!,
|
|
146
|
+
bounds = bounds,
|
|
147
|
+
zoomRange = ZoomRange(
|
|
148
|
+
minZoom = options.getInt("minZoom").toByte(),
|
|
149
|
+
maxZoom = options.getInt("maxZoom").toByte()
|
|
150
|
+
),
|
|
151
|
+
metadata = metadata
|
|
152
|
+
)
|
|
153
|
+
tileRegionPacks[id] = actPack
|
|
154
|
+
startLoading(pack = actPack)
|
|
155
|
+
promise.resolve(
|
|
156
|
+
writableMapOf("bounds" to boundsStr, "metadata" to metadataStr)
|
|
157
|
+
)
|
|
158
|
+
} catch (e: Throwable) {
|
|
159
|
+
promise.reject("createPack", e)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@ReactMethod
|
|
164
|
+
fun getPackStatus(name: String, promise: Promise) {
|
|
165
|
+
val pack = tileRegionPacks[name]
|
|
166
|
+
if (pack != null) {
|
|
167
|
+
promise.resolve(makeRegionStatus(name, pack.progress, pack))
|
|
168
|
+
} else {
|
|
169
|
+
promise.reject(Error("Pack not found"))
|
|
170
|
+
Logger.w(REACT_CLASS, "getPackStatus - Unknown offline region")
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@ReactMethod
|
|
175
|
+
fun resumePackDownload(name: String, promise: Promise) {
|
|
176
|
+
val pack = tileRegionPacks[name]
|
|
177
|
+
if (pack != null) {
|
|
178
|
+
startLoading(pack)
|
|
179
|
+
promise.resolve(null)
|
|
180
|
+
} else {
|
|
181
|
+
promise.reject("resumePackDownload", "Unknown offline pack: $name")
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@ReactMethod
|
|
186
|
+
fun pausePackDownload(name: String, promise: Promise) {
|
|
187
|
+
val pack = tileRegionPacks[name]
|
|
188
|
+
if (pack != null) {
|
|
189
|
+
if (pack.cancelable != null) {
|
|
190
|
+
pack.cancelable?.cancel()
|
|
191
|
+
pack.cancelable = null
|
|
192
|
+
promise.resolve(null)
|
|
193
|
+
} else {
|
|
194
|
+
promise.reject("resumeRegionDownload", "Offline pack: $name already cancelled")
|
|
195
|
+
}
|
|
196
|
+
} else {
|
|
197
|
+
promise.reject("resumeRegionDownload", "Unknown offline region")
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@ReactMethod
|
|
202
|
+
fun setTileCountLimit(tileCountLimit: Int) {
|
|
203
|
+
val offlineRegionManager = OfflineRegionManager(ResourceOptions.Builder().accessToken(RCTMGLModule.getAccessToken(mReactContext)).build())
|
|
204
|
+
offlineRegionManager.setOfflineMapboxTileCountLimit(tileCountLimit.toLong())
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@ReactMethod
|
|
208
|
+
fun deletePack(name: String, promise: Promise) {
|
|
209
|
+
val pack = tileRegionPacks[name]
|
|
210
|
+
|
|
211
|
+
if (pack == null) {
|
|
212
|
+
promise.resolve(null)
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (pack.state == TileRegionPackState.INVALID) {
|
|
217
|
+
promise.reject("deletePack", "Pack: $name has already been deleted")
|
|
218
|
+
return
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
tileStore.removeTileRegion(name, object: TileRegionCallback {
|
|
222
|
+
override fun run(expected: Expected<TileRegionError, TileRegion>) {
|
|
223
|
+
expected.value.also {
|
|
224
|
+
tileRegionPacks[name]!!.state = TileRegionPackState.INVALID
|
|
225
|
+
promise.resolve(null);
|
|
226
|
+
} ?: run {
|
|
227
|
+
promise.reject("deletePack", expected.error?.message ?: "n/a")
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@ReactMethod
|
|
234
|
+
fun getPacks(promise: Promise) {
|
|
235
|
+
tileStore.getAllTileRegions(object : TileRegionsCallback {
|
|
236
|
+
override fun run(expected: Expected<TileRegionError, List<TileRegion>>) {
|
|
237
|
+
UiThreadUtil.runOnUiThread(object : Runnable {
|
|
238
|
+
override fun run() {
|
|
239
|
+
expected.value?.also { regions ->
|
|
240
|
+
convertRegionsToJSON(regions, promise)
|
|
241
|
+
} ?: run {
|
|
242
|
+
promise.reject("getPacks", expected.error!!.message)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// endregion
|
|
251
|
+
|
|
252
|
+
fun startLoading(pack: TileRegionPack) {
|
|
253
|
+
val id = pack.name
|
|
254
|
+
val bounds = pack.bounds
|
|
255
|
+
if (bounds == null) {
|
|
256
|
+
throw IllegalArgumentException("startLoading failed as there are no bounds in pack")
|
|
257
|
+
}
|
|
258
|
+
val zoomRange = pack.zoomRange
|
|
259
|
+
if (zoomRange == null) {
|
|
260
|
+
throw IllegalArgumentException("startLoading failed as there is no zoomRange in pack")
|
|
261
|
+
}
|
|
262
|
+
val styleURI = pack.styleURI
|
|
263
|
+
if (styleURI == null) {
|
|
264
|
+
throw IllegalArgumentException("startLoading failed as there is no styleURI in pack")
|
|
265
|
+
}
|
|
266
|
+
val metadata = pack.metadata
|
|
267
|
+
if (metadata == null) {
|
|
268
|
+
throw IllegalArgumentException("startLoading failed as there is no metadata in pack")
|
|
269
|
+
}
|
|
270
|
+
val stylePackOptions = StylePackLoadOptions.Builder()
|
|
271
|
+
.glyphsRasterizationMode(GlyphsRasterizationMode.IDEOGRAPHS_RASTERIZED_LOCALLY)
|
|
272
|
+
.metadata(metadata.toMapboxValue())
|
|
273
|
+
.build()
|
|
274
|
+
|
|
275
|
+
val descriptorOptions = TilesetDescriptorOptions.Builder()
|
|
276
|
+
.styleURI(styleURI)
|
|
277
|
+
.minZoom(zoomRange.minZoom)
|
|
278
|
+
.maxZoom(zoomRange.maxZoom)
|
|
279
|
+
.stylePackOptions(stylePackOptions)
|
|
80
280
|
.build()
|
|
81
281
|
val tilesetDescriptor = offlineManager.createTilesetDescriptor(descriptorOptions)
|
|
82
|
-
|
|
83
|
-
descriptors.add(tilesetDescriptor)
|
|
282
|
+
|
|
84
283
|
val loadOptions = TileRegionLoadOptions.Builder()
|
|
85
|
-
.geometry(
|
|
86
|
-
.descriptors(
|
|
87
|
-
.metadata(
|
|
284
|
+
.geometry(bounds)
|
|
285
|
+
.descriptors(arrayListOf(tilesetDescriptor))
|
|
286
|
+
.metadata(metadata.toMapboxValue())
|
|
88
287
|
.acceptExpired(true)
|
|
89
288
|
.networkRestriction(NetworkRestriction.NONE)
|
|
289
|
+
.averageBytesPerSecond(null)
|
|
90
290
|
.build()
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
val
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
291
|
+
|
|
292
|
+
var lastProgress: TileRegionLoadProgress? = null
|
|
293
|
+
val task = this.tileStore.loadTileRegion(
|
|
294
|
+
id, loadOptions,
|
|
295
|
+
{ progress ->
|
|
296
|
+
lastProgress = progress
|
|
297
|
+
tileRegionPacks[id]!!.progress = progress
|
|
298
|
+
tileRegionPacks[id]!!.state = TileRegionPackState.ACTIVE
|
|
299
|
+
|
|
300
|
+
offlinePackProgressDidChange(progress, metadata, TileRegionPackState.ACTIVE)
|
|
301
|
+
}, { expected ->
|
|
302
|
+
expected.value?.also {
|
|
303
|
+
val progress = lastProgress
|
|
304
|
+
if (progress != null) {
|
|
305
|
+
offlinePackProgressDidChange(progress, metadata, TileRegionPackState.COMPLETE)
|
|
306
|
+
} else {
|
|
307
|
+
Logger.w(LOG_TAG, "startLoading: tile region completed, but got no progress information")
|
|
308
|
+
}
|
|
309
|
+
tileRegionPacks[id]!!.state = TileRegionPackState.COMPLETE
|
|
310
|
+
} ?: run {
|
|
311
|
+
val error = expected.error ?: TileRegionError(TileRegionErrorType.OTHER, "$LOG_TAG neither value nor error in expected")
|
|
312
|
+
|
|
313
|
+
tileRegionPacks[id]!!.state = TileRegionPackState.INACTIVE
|
|
314
|
+
offlinePackDidReceiveError(name=id, error=error)
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
)
|
|
318
|
+
tileRegionPacks[id]!!.cancelable = task
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
private fun convertRegionsToJSON(tileRegions: List<TileRegion>, promise: Promise) {
|
|
322
|
+
val countDownLatch = CountDownLatch(tileRegions.size * 2)
|
|
323
|
+
val foo = mutableMapOf<String,Pair<Expected<TileRegionError,Geometry>, TileRegion>>()
|
|
324
|
+
val geometryResults = mutableMapOf<String, Pair<Expected<TileRegionError, Geometry>,TileRegion>>();
|
|
325
|
+
val metadataResults = mutableMapOf<String, Expected<TileRegionError, Value>>()
|
|
326
|
+
val errors = ArrayList<TileRegionError?>()
|
|
327
|
+
try {
|
|
328
|
+
for (region: TileRegion in tileRegions) {
|
|
329
|
+
tileStore.getTileRegionGeometry(region.id
|
|
330
|
+
) { result ->
|
|
331
|
+
geometryResults[region.id] = Pair(result, region)
|
|
332
|
+
countDownLatch.countDown()
|
|
333
|
+
}
|
|
334
|
+
tileStore.getTileRegionMetadata(region.id) { result ->
|
|
335
|
+
metadataResults[region.id] = result
|
|
336
|
+
countDownLatch.countDown()
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
} catch (error: Error) {
|
|
340
|
+
Logger.e(LOG_TAG, "convertRegionsToJSON. failed to iterate regions")
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
try {
|
|
344
|
+
countDownLatch.await()
|
|
345
|
+
|
|
346
|
+
val firstError = geometryResults.firstNotNullOfOrNull { (id,pair) -> pair.first.error }
|
|
347
|
+
if (firstError != null) {
|
|
348
|
+
promise.reject("convertRegionsToJSON", firstError.message)
|
|
349
|
+
return
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
val results = geometryResults.map { (id, pair) ->
|
|
353
|
+
val (expected, region) = pair
|
|
354
|
+
val geometry = expected.value!!
|
|
355
|
+
return@map Pair(id, Triple(geometry, region, metadataResults[id]?.value))
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
promise.resolve(
|
|
359
|
+
writableArrayOf(
|
|
360
|
+
*results.map { (id,geometry_region_metadata) ->
|
|
361
|
+
val (geometry, region, metadata) = geometry_region_metadata
|
|
362
|
+
val metadataJSON = metadata?.toJSONObject()
|
|
363
|
+
val ret = convertRegionToJSON(region, geometry, metadataJSON)
|
|
364
|
+
val pack = tileRegionPacks[region.id] ?: TileRegionPack(
|
|
365
|
+
name= region.id,
|
|
366
|
+
state= TileRegionPackState.UNKNOWN,
|
|
367
|
+
progress= toProgress(region),
|
|
368
|
+
metadata= metadataJSON ?: JSONObject()
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
if (region.completedResourceCount == region.requiredResourceCount) {
|
|
372
|
+
pack.state = TileRegionPackState.COMPLETE
|
|
373
|
+
}
|
|
374
|
+
tileRegionPacks[region.id] = pack
|
|
375
|
+
return@map ret
|
|
376
|
+
}.toTypedArray())
|
|
377
|
+
)
|
|
378
|
+
} catch (interruptedException: InterruptedException) {
|
|
379
|
+
promise.reject(interruptedException)
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
private fun convertRegionToJSON(region: TileRegion, geometry: Geometry, metadata: JSONObject?): ReadableMap {
|
|
384
|
+
val bb = geometry.calculateBoundingBox()
|
|
385
|
+
|
|
386
|
+
val jsonBounds = writableArrayOf(
|
|
387
|
+
bb.northeast().longitude(),
|
|
388
|
+
bb.northeast().latitude(),
|
|
389
|
+
bb.southwest().longitude(),
|
|
390
|
+
bb.southwest().latitude()
|
|
391
|
+
)
|
|
392
|
+
val completed = (region.completedResourceCount == region.requiredResourceCount)
|
|
393
|
+
|
|
394
|
+
val metadataOrEmpty = metadata ?: JSONObject()
|
|
395
|
+
val metadataWithName = metadataOrEmpty.put("name", region.id)
|
|
396
|
+
|
|
397
|
+
var result = writableMapOf(
|
|
398
|
+
"requiredResourceCount" to region.requiredResourceCount,
|
|
399
|
+
"completedResourceCount" to region.completedResourceCount,
|
|
400
|
+
"completedResourceSize" to region.completedResourceSize,
|
|
401
|
+
"state" to (if (completed) TileRegionPackState.COMPLETE.rawValue else TileRegionPackState.UNKNOWN ),
|
|
402
|
+
"metadata" to metadataWithName.toString(),
|
|
403
|
+
"bounds" to jsonBounds,
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
if (region.requiredResourceCount > 0) {
|
|
407
|
+
val percentage = 100.0 * region.completedResourceCount.toDouble() / region.requiredResourceCount.toDouble()
|
|
408
|
+
result.putDouble("percentage", percentage)
|
|
409
|
+
} else {
|
|
410
|
+
result.putNull("percentage")
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
val expires = region.expires
|
|
414
|
+
if (expires != null) {
|
|
415
|
+
result.putString("expires", expires.toString())
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return result
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
private fun toProgress(region: TileRegion): TileRegionLoadProgress {
|
|
422
|
+
return TileRegionLoadProgress(
|
|
423
|
+
region.completedResourceCount,
|
|
424
|
+
region.completedResourceSize,
|
|
425
|
+
0,
|
|
426
|
+
region.requiredResourceCount,
|
|
427
|
+
0,
|
|
428
|
+
0
|
|
429
|
+
)
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
private fun _makeRegionStatusPayload(name:String, progress: TileRegionLoadProgress?,state: TileRegionPackState, metadata: JSONObject?) : WritableMap {
|
|
433
|
+
var result = Arguments.createMap()
|
|
434
|
+
if (progress != null) {
|
|
435
|
+
val progressPercentage = progress.completedResourceCount.toDouble() / progress.requiredResourceCount.toDouble()
|
|
436
|
+
result = writableMapOf(
|
|
437
|
+
"state" to (if (progress.completedResourceCount == progress.requiredResourceCount) TileRegionPackState.COMPLETE.rawValue else state.rawValue),
|
|
438
|
+
"name" to name,
|
|
439
|
+
"perentage" to progressPercentage * 100.0,
|
|
440
|
+
"completedResourceCount" to progress.completedResourceCount,
|
|
441
|
+
"completedResourceSize" to progress.completedResourceSize,
|
|
442
|
+
"erroredResourceCount" to progress.erroredResourceCount,
|
|
443
|
+
"loadedResourceSize" to progress.loadedResourceSize,
|
|
444
|
+
"loadedResourceCount" to progress.loadedResourceCount,
|
|
445
|
+
"requiredResourceCount" to progress.requiredResourceCount
|
|
446
|
+
)
|
|
447
|
+
} else {
|
|
448
|
+
result = writableMapOf(
|
|
449
|
+
"state" to state.rawValue,
|
|
450
|
+
"name" to name,
|
|
451
|
+
"perentage" to null,
|
|
452
|
+
)
|
|
453
|
+
}
|
|
454
|
+
if (metadata != null) {
|
|
455
|
+
result.putMap("metadata", metadata.toReadableMap())
|
|
456
|
+
}
|
|
457
|
+
return result
|
|
458
|
+
}
|
|
459
|
+
private fun makeProgresEvent(name: String, progress: TileRegionLoadProgress, state: TileRegionPackState): OfflineEvent {
|
|
460
|
+
return OfflineEvent(
|
|
461
|
+
OFFLINE_PROGRESS,
|
|
462
|
+
EventTypes.OFFLINE_STATUS,
|
|
463
|
+
_makeRegionStatusPayload(name, progress, state, null)
|
|
464
|
+
)
|
|
465
|
+
}
|
|
466
|
+
private fun offlinePackProgressDidChange(progress: TileRegionLoadProgress, metadata: JSONObject, state: TileRegionPackState) {
|
|
467
|
+
// TODO throttle
|
|
468
|
+
sendEvent(this.makeProgresEvent(metadata.getString("name"), progress, state))
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
private fun offlinePackDidReceiveError(name: String, error: TileRegionError) {
|
|
472
|
+
val event = OfflineEvent(
|
|
473
|
+
OFFLINE_ERROR,
|
|
474
|
+
EventTypes.OFFLINE_ERROR,
|
|
475
|
+
writableMapOf(
|
|
476
|
+
"name" to name,
|
|
477
|
+
"message" to error.message
|
|
478
|
+
)
|
|
479
|
+
)
|
|
480
|
+
sendEvent(event)
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
private fun convertPointPairToBounds(boundsFC: FeatureCollection): Geometry {
|
|
484
|
+
val geometryCollection = boundsFC.toGeometryCollection()
|
|
485
|
+
val geometries = geometryCollection.geometries()
|
|
486
|
+
if (geometries.size != 2) {
|
|
487
|
+
return geometryCollection
|
|
488
|
+
}
|
|
489
|
+
val g0 = geometries.get(0) as Point?
|
|
490
|
+
val g1 = geometries.get(1) as Point?
|
|
491
|
+
if (g0 == null || g1 == null) {
|
|
492
|
+
return geometryCollection
|
|
493
|
+
}
|
|
494
|
+
val pt0 = g0
|
|
495
|
+
val pt1 = g1
|
|
496
|
+
return Polygon.fromLngLats(
|
|
497
|
+
listOf(
|
|
498
|
+
listOf(
|
|
499
|
+
pt0,
|
|
500
|
+
Point.fromLngLat(pt1.longitude(), pt0.latitude()),
|
|
501
|
+
pt1,
|
|
502
|
+
Point.fromLngLat(pt0.longitude(), pt1.latitude()),
|
|
503
|
+
pt0
|
|
504
|
+
))
|
|
505
|
+
)
|
|
99
506
|
}
|
|
100
507
|
|
|
101
508
|
fun startPackDownload(pack: TileRegionPack) {
|
|
102
509
|
val _this = this
|
|
103
|
-
pack.cancelable =
|
|
510
|
+
pack.cancelable = tileStore
|
|
104
511
|
.loadTileRegion(
|
|
105
512
|
pack.name,
|
|
106
513
|
(pack.loadOptions)!!,
|
|
107
514
|
TileRegionLoadProgressCallback { progress ->
|
|
108
515
|
pack.progress = progress
|
|
109
|
-
pack.state =
|
|
516
|
+
pack.state = TileRegionPackState.ACTIVE
|
|
110
517
|
_this.sendEvent(_this.makeStatusEvent(pack.name, progress, pack))
|
|
111
518
|
},
|
|
112
519
|
object : TileRegionCallback {
|
|
113
520
|
override fun run(region: Expected<TileRegionError, TileRegion>) {
|
|
114
521
|
pack.cancelable = null
|
|
115
522
|
if (region.isError) {
|
|
116
|
-
pack.state =
|
|
523
|
+
pack.state = TileRegionPackState.INACTIVE
|
|
117
524
|
_this.sendEvent(
|
|
118
525
|
_this.makeErrorEvent(
|
|
119
526
|
pack.name, "TileRegionError", region.error!!
|
|
@@ -121,82 +528,21 @@ class RCTMGLOfflineModule(private val mReactContext: ReactApplicationContext) :
|
|
|
121
528
|
)
|
|
122
529
|
)
|
|
123
530
|
} else {
|
|
124
|
-
pack.state =
|
|
531
|
+
pack.state = TileRegionPackState.COMPLETE
|
|
125
532
|
_this.sendEvent(_this.makeStatusEvent(pack.name, pack.progress, pack))
|
|
126
533
|
}
|
|
127
534
|
}
|
|
128
535
|
})
|
|
129
536
|
}
|
|
130
537
|
|
|
131
|
-
@ReactMethod
|
|
132
|
-
fun getPacks(promise: Promise) {
|
|
133
|
-
getTileStore().getAllTileRegions(object : TileRegionsCallback {
|
|
134
|
-
override fun run(regions: Expected<TileRegionError, List<TileRegion>>) {
|
|
135
|
-
UiThreadUtil.runOnUiThread(object : Runnable {
|
|
136
|
-
override fun run() {
|
|
137
|
-
if (regions.isValue) {
|
|
138
|
-
convertRegionsToJSON((regions.value)!!, promise)
|
|
139
|
-
} else {
|
|
140
|
-
promise.reject("getPacks", regions.error!!.message)
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
})
|
|
144
|
-
}
|
|
145
|
-
})
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
private fun convertRegionsToJSON(tileRegions: List<TileRegion>, promise: Promise) {
|
|
149
|
-
val countDownLatch = CountDownLatch(tileRegions.size)
|
|
150
|
-
val errors = ArrayList<TileRegionError?>()
|
|
151
|
-
val geometries = ArrayList<Geometry>()
|
|
152
|
-
try {
|
|
153
|
-
for (region: TileRegion in tileRegions) {
|
|
154
|
-
getTileStore()
|
|
155
|
-
.getTileRegionGeometry(region.id, object : TileRegionGeometryCallback {
|
|
156
|
-
override fun run(result: Expected<TileRegionError, Geometry>) {
|
|
157
|
-
if (result.isValue) {
|
|
158
|
-
geometries.add(result.value!!)
|
|
159
|
-
} else {
|
|
160
|
-
errors.add(result.error)
|
|
161
|
-
}
|
|
162
|
-
countDownLatch.countDown()
|
|
163
|
-
}
|
|
164
|
-
})
|
|
165
|
-
}
|
|
166
|
-
} catch (error: Error) {
|
|
167
|
-
Logger.e("OS", "a")
|
|
168
|
-
}
|
|
169
|
-
try {
|
|
170
|
-
countDownLatch.await()
|
|
171
|
-
val result = Arguments.createArray()
|
|
172
|
-
for (geometry: Geometry in geometries) {
|
|
173
|
-
result.pushMap(fromOfflineRegion(geometry))
|
|
174
|
-
}
|
|
175
|
-
for (error: TileRegionError? in errors) {
|
|
176
|
-
val errorMap = Arguments.createMap()
|
|
177
|
-
errorMap.putString("type", "error")
|
|
178
|
-
errorMap.putString("message", error!!.message)
|
|
179
|
-
errorMap.putString("errorType", error.type.toString())
|
|
180
|
-
result.pushMap(errorMap)
|
|
181
|
-
}
|
|
182
|
-
promise.resolve(
|
|
183
|
-
result
|
|
184
|
-
)
|
|
185
|
-
} catch (interruptedException: InterruptedException) {
|
|
186
|
-
promise.reject(interruptedException)
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
538
|
@ReactMethod
|
|
191
539
|
fun resetDatabase(promise: Promise) {
|
|
192
|
-
val tileStore = getTileStore()
|
|
193
540
|
tileStore.getAllTileRegions { expected ->
|
|
194
541
|
expected.value?.also { tileRegions ->
|
|
195
542
|
tileRegions.forEach { tileRegion ->
|
|
196
543
|
tileStore.removeTileRegion(tileRegion.id);
|
|
197
544
|
}
|
|
198
545
|
|
|
199
|
-
val offlineManager = getOfflineManager(mReactContext)
|
|
200
546
|
offlineManager.getAllStylePacks { expected ->
|
|
201
547
|
expected.value?.also { stylePacks ->
|
|
202
548
|
stylePacks.forEach { stylePack ->
|
|
@@ -218,173 +564,32 @@ class RCTMGLOfflineModule(private val mReactContext: ReactApplicationContext) :
|
|
|
218
564
|
|
|
219
565
|
}
|
|
220
566
|
|
|
221
|
-
@ReactMethod
|
|
222
|
-
fun getPackStatus(name: String, promise: Promise) {
|
|
223
|
-
val pack = tileRegionPacks[name]
|
|
224
|
-
if (pack != null) {
|
|
225
|
-
promise.resolve(makeRegionStatus(name, pack.progress, pack))
|
|
226
|
-
} else {
|
|
227
|
-
promise.reject(Error("Pack not found"))
|
|
228
|
-
Logger.w(REACT_CLASS, "getPackStatus - Unknown offline region")
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/*
|
|
233
|
-
@ReactMethod
|
|
234
|
-
public void setPackObserver(final String name, final Promise promise) {
|
|
235
|
-
activateFileSource();
|
|
236
|
-
|
|
237
|
-
final OfflineManager offlineManager = OfflineManager.getInstance(mReactContext);
|
|
238
|
-
|
|
239
|
-
offlineManager.listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
|
|
240
|
-
@Override
|
|
241
|
-
public void onList(OfflineRegion[] offlineRegions) {
|
|
242
|
-
OfflineRegion region = getRegionByName(name, offlineRegions);
|
|
243
|
-
boolean hasRegion = region != null;
|
|
244
|
-
|
|
245
|
-
if (hasRegion) {
|
|
246
|
-
setOfflineRegionObserver(name, region);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
promise.resolve(hasRegion);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
@Override
|
|
253
|
-
public void onError(String error) {
|
|
254
|
-
promise.reject("setPackObserver", error);
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
|
-
}*/
|
|
258
|
-
/*
|
|
259
|
-
@ReactMethod
|
|
260
|
-
public void invalidatePack(final String name, final Promise promise) {
|
|
261
|
-
activateFileSource();
|
|
262
|
-
|
|
263
|
-
final OfflineManager offlineManager = OfflineManager.getInstance(mReactContext);
|
|
264
|
-
|
|
265
|
-
offlineManager.listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
|
|
266
|
-
@Override
|
|
267
|
-
public void onList(OfflineRegion[] offlineRegions) {
|
|
268
|
-
OfflineRegion region = getRegionByName(name, offlineRegions);
|
|
269
|
-
|
|
270
|
-
if (region == null) {
|
|
271
|
-
promise.resolve(null);
|
|
272
|
-
Log.w(REACT_CLASS, "invalidateRegion - Unknown offline region");
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
region.invalidate(new OfflineRegion.OfflineRegionInvalidateCallback() {
|
|
277
|
-
@Override
|
|
278
|
-
public void onInvalidate() {
|
|
279
|
-
promise.resolve(null);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
@Override
|
|
283
|
-
public void onError(String error) {
|
|
284
|
-
promise.reject("invalidateRegion", error);
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
@Override
|
|
290
|
-
public void onError(String error) {
|
|
291
|
-
promise.reject("invalidateRegion", error);
|
|
292
|
-
}
|
|
293
|
-
});
|
|
294
|
-
}*/
|
|
295
|
-
|
|
296
|
-
@ReactMethod
|
|
297
|
-
fun deletePack(name: String, promise: Promise) {
|
|
298
|
-
getTileStore().getAllTileRegions{ expected ->
|
|
299
|
-
if (expected.isValue) {
|
|
300
|
-
expected.value?.let { tileRegionList ->
|
|
301
|
-
var downloadedRegionExists = false;
|
|
302
|
-
for (tileRegion in tileRegionList) {
|
|
303
|
-
if (tileRegion.id == name) {
|
|
304
|
-
downloadedRegionExists = true;
|
|
305
|
-
getTileStore()!!.removeTileRegion(name, object : TileRegionCallback {
|
|
306
|
-
override fun run(region: Expected<TileRegionError, TileRegion>) {
|
|
307
|
-
promise.resolve(null);
|
|
308
|
-
}
|
|
309
|
-
})
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if (!downloadedRegionExists) {
|
|
313
|
-
promise.resolve(null);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
expected.error?.let { tileRegionError ->
|
|
318
|
-
promise.reject("deletePack", "TileRegionError: $tileRegionError")
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
567
|
@ReactMethod
|
|
324
568
|
fun migrateOfflineCache() {
|
|
569
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
570
|
+
// Old and new cache file paths
|
|
571
|
+
val targetPathName = mReactContext.filesDir.absolutePath + "/.mapbox/map_data"
|
|
572
|
+
val sourcePath = Paths.get(mReactContext.filesDir.absolutePath + "/mbgl-offline.db")
|
|
573
|
+
val targetPath = Paths.get(targetPathName + "/map_data.db")
|
|
325
574
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
directory.mkdirs()
|
|
334
|
-
Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING)
|
|
335
|
-
Log.d("TAG","v10 cache directory created successfully")
|
|
336
|
-
} catch (e: Exception) {
|
|
337
|
-
Log.d("TAG", "${e}... file move unsuccessful")
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
@ReactMethod
|
|
342
|
-
fun pausePackDownload(name: String, promise: Promise) {
|
|
343
|
-
val pack = tileRegionPacks[name]
|
|
344
|
-
if (pack != null) {
|
|
345
|
-
if (pack.cancelable != null) {
|
|
346
|
-
pack.cancelable!!.cancel()
|
|
347
|
-
pack.cancelable = null
|
|
348
|
-
promise.resolve(null)
|
|
349
|
-
} else {
|
|
350
|
-
promise.reject("resumeRegionDownload", "Offline region cancelled already")
|
|
575
|
+
try {
|
|
576
|
+
val directory = File(targetPathName)
|
|
577
|
+
directory.mkdirs()
|
|
578
|
+
Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING)
|
|
579
|
+
Log.d(LOG_TAG, "v10 cache directory created successfully")
|
|
580
|
+
} catch (e: Exception) {
|
|
581
|
+
Log.d(LOG_TAG, "${e}... file move unsuccessful")
|
|
351
582
|
}
|
|
352
583
|
} else {
|
|
353
|
-
|
|
584
|
+
Logger.w(LOG_TAG, "migrateOfflineCache only supported on api level 26 or later")
|
|
354
585
|
}
|
|
355
586
|
}
|
|
356
587
|
|
|
357
|
-
@ReactMethod
|
|
358
|
-
fun resumePackDownload(name: String, promise: Promise) {
|
|
359
|
-
val pack = tileRegionPacks[name]
|
|
360
|
-
if (pack != null) {
|
|
361
|
-
startPackDownload(pack)
|
|
362
|
-
promise.resolve(null)
|
|
363
|
-
} else {
|
|
364
|
-
promise.reject("resumeRegionDownload", "Unknown offline region")
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
@ReactMethod
|
|
369
|
-
fun setTileCountLimit(tileCountLimit: Int) {
|
|
370
|
-
val offlineRegionManager = OfflineRegionManager(ResourceOptions.Builder().accessToken(RCTMGLModule.getAccessToken(mReactContext)).build())
|
|
371
|
-
offlineRegionManager.setOfflineMapboxTileCountLimit(tileCountLimit.toLong())
|
|
372
|
-
}
|
|
373
|
-
|
|
374
588
|
@ReactMethod
|
|
375
589
|
fun setProgressEventThrottle(eventThrottle: Double) {
|
|
376
590
|
mProgressEventThrottle = eventThrottle
|
|
377
591
|
}
|
|
378
592
|
|
|
379
|
-
/*
|
|
380
|
-
private OfflineRegionDefinition makeDefinition(LatLngBounds latLngBounds, ReadableMap options) {
|
|
381
|
-
return new OfflineTilePyramidRegionDefinition(
|
|
382
|
-
ConvertUtils.getString("styleURL", options, DEFAULT_STYLE_URL),
|
|
383
|
-
latLngBounds,
|
|
384
|
-
ConvertUtils.getDouble("minZoom", options, DEFAULT_MIN_ZOOM_LEVEL),
|
|
385
|
-
ConvertUtils.getDouble("maxZoom", options, DEFAULT_MAX_ZOOM_LEVEL),
|
|
386
|
-
mReactContext.getResources().getDisplayMetrics().density);
|
|
387
|
-
}*/
|
|
388
593
|
private fun getMetadataBytes(metadata: String?): ByteArray? {
|
|
389
594
|
var metadataBytes: ByteArray? = null
|
|
390
595
|
if (metadata == null || metadata.isEmpty()) {
|
|
@@ -398,51 +603,6 @@ class RCTMGLOfflineModule(private val mReactContext: ReactApplicationContext) :
|
|
|
398
603
|
return metadataBytes
|
|
399
604
|
}
|
|
400
605
|
|
|
401
|
-
/*
|
|
402
|
-
private void setOfflineRegionObserver(final String name, final OfflineRegion region) {
|
|
403
|
-
region.setObserver(new OfflineRegion.OfflineRegionObserver() {
|
|
404
|
-
OfflineRegionStatus prevStatus = null;
|
|
405
|
-
long timestamp = System.currentTimeMillis();
|
|
406
|
-
|
|
407
|
-
@Override
|
|
408
|
-
public void onStatusChanged(OfflineRegionStatus status) {
|
|
409
|
-
if (shouldSendUpdate(System.currentTimeMillis(), status)) {
|
|
410
|
-
sendEvent(makeStatusEvent(name, status));
|
|
411
|
-
timestamp = System.currentTimeMillis();
|
|
412
|
-
}
|
|
413
|
-
prevStatus = status;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
@Override
|
|
417
|
-
public void onError(OfflineRegionError error) {
|
|
418
|
-
sendEvent(makeErrorEvent(name, EventTypes.OFFLINE_ERROR, error.getMessage()));
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
@Override
|
|
422
|
-
public void mapboxTileCountLimitExceeded(long limit) {
|
|
423
|
-
String message = String.format(Locale.getDefault(), "Mapbox tile limit exceeded %d", limit);
|
|
424
|
-
sendEvent(makeErrorEvent(name, EventTypes.OFFLINE_TILE_LIMIT, message));
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
private boolean shouldSendUpdate (long currentTimestamp, OfflineRegionStatus curStatus) {
|
|
428
|
-
if (prevStatus == null) {
|
|
429
|
-
return false;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
if (prevStatus.getDownloadState() != curStatus.getDownloadState()) {
|
|
433
|
-
return true;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
if (currentTimestamp - timestamp > mProgressEventThrottle) {
|
|
437
|
-
return true;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
return false;
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
region.setDownloadState(ACTIVE_REGION_DOWNLOAD_STATE);
|
|
445
|
-
}*/
|
|
446
606
|
private fun sendEvent(event: IEvent) {
|
|
447
607
|
val eventEmitter = eventEmitter
|
|
448
608
|
eventEmitter.emit(event.key, event.toJSON())
|
|
@@ -483,7 +643,7 @@ class RCTMGLOfflineModule(private val mReactContext: ReactApplicationContext) :
|
|
|
483
643
|
val progressPercentage =
|
|
484
644
|
(status!!.completedResourceCount.toDouble() * 100.0) / (status.requiredResourceCount.toDouble())
|
|
485
645
|
map.putString("name", regionName)
|
|
486
|
-
map.putString("state", pack.state)
|
|
646
|
+
map.putString("state", pack.state.rawValue)
|
|
487
647
|
map.putDouble("percentage", progressPercentage)
|
|
488
648
|
map.putInt("completedResourceCount", status.completedResourceCount.toInt())
|
|
489
649
|
map.putInt("completedResourceSize", status.completedResourceSize.toInt())
|
|
@@ -494,107 +654,16 @@ class RCTMGLOfflineModule(private val mReactContext: ReactApplicationContext) :
|
|
|
494
654
|
return map
|
|
495
655
|
}
|
|
496
656
|
|
|
497
|
-
|
|
498
|
-
val
|
|
499
|
-
val
|
|
500
|
-
|
|
501
|
-
|
|
657
|
+
companion object {
|
|
658
|
+
const val REACT_CLASS = "RCTMGLOfflineModule"
|
|
659
|
+
const val LOG_TAG = REACT_CLASS
|
|
660
|
+
const val OFFLINE_ERROR = "MapboxOfflineRegionError"
|
|
661
|
+
const val OFFLINE_PROGRESS = "MapboxOfflineRegionProgress"
|
|
502
662
|
|
|
503
|
-
private fun fromOfflineRegion(bounds: LatLngBounds, metadataStr: String?): WritableMap {
|
|
504
|
-
val map = Arguments.createMap()
|
|
505
|
-
map.putArray("bounds", GeoJSONUtils.fromLatLngBounds(bounds))
|
|
506
|
-
map.putString("metadata", metadataStr)
|
|
507
|
-
return map
|
|
508
663
|
}
|
|
664
|
+
}
|
|
509
665
|
|
|
510
|
-
private fun fromOfflineRegion(region: Geometry): WritableMap {
|
|
511
|
-
val map = Arguments.createMap()
|
|
512
|
-
val bbox = TurfMeasurement.bbox(region)
|
|
513
|
-
val bounds = Arguments.createArray()
|
|
514
|
-
for (d: Double in bbox) {
|
|
515
|
-
bounds.pushDouble(d)
|
|
516
|
-
}
|
|
517
|
-
map.putArray("bounds", bounds)
|
|
518
|
-
map.putMap("geometry", GeoJSONUtils.fromGeometry(region))
|
|
519
|
-
|
|
520
|
-
//map.putString("metadata", new String(region.getMetadata()));
|
|
521
|
-
return map
|
|
522
|
-
} /*
|
|
523
|
-
private OfflineRegion getRegionByName(String name, OfflineRegion[] offlineRegions) {
|
|
524
|
-
if (name == null || name.isEmpty()) {
|
|
525
|
-
return null;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
for (OfflineRegion region : offlineRegions) {
|
|
529
|
-
boolean isRegion = false;
|
|
530
|
-
|
|
531
|
-
try {
|
|
532
|
-
byte[] byteMetadata = region.getMetadata();
|
|
533
|
-
|
|
534
|
-
if (byteMetadata != null) {
|
|
535
|
-
JSONObject metadata = new JSONObject(new String(byteMetadata));
|
|
536
|
-
isRegion = name.equals(metadata.getString("name"));
|
|
537
|
-
}
|
|
538
|
-
} catch (JSONException e) {
|
|
539
|
-
Log.w(REACT_CLASS, e.getLocalizedMessage());
|
|
540
|
-
}
|
|
541
666
|
|
|
542
|
-
if (isRegion) {
|
|
543
|
-
return region;
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
667
|
|
|
547
|
-
return null;
|
|
548
|
-
}*/
|
|
549
668
|
|
|
550
|
-
/*
|
|
551
|
-
private void activateFileSource() {
|
|
552
|
-
FileSource fileSource = FileSource.getInstance(mReactContext);
|
|
553
|
-
fileSource.activate();
|
|
554
|
-
}*/
|
|
555
|
-
companion object {
|
|
556
|
-
const val REACT_CLASS = "RCTMGLOfflineModule"
|
|
557
|
-
const val LOG_TAG = REACT_CLASS
|
|
558
|
-
@JvmField
|
|
559
|
-
val INACTIVE_REGION_DOWNLOAD_STATE = TileRegionPack.INACTIVE
|
|
560
|
-
@JvmField
|
|
561
|
-
val ACTIVE_REGION_DOWNLOAD_STATE = TileRegionPack.ACTIVE
|
|
562
|
-
@JvmField
|
|
563
|
-
val COMPLETE_REGION_DOWNLOAD_STATE = TileRegionPack.COMPLETE
|
|
564
|
-
@JvmField
|
|
565
|
-
val OFFLINE_ERROR = "MapboxOfflineRegionError"
|
|
566
|
-
@JvmField
|
|
567
|
-
val OFFLINE_PROGRESS = "MapboxOfflineRegionProgress"
|
|
568
|
-
|
|
569
|
-
// public static final String DEFAULT_STYLE_URL = Style.MAPBOX_STREETS;
|
|
570
|
-
val DEFAULT_MIN_ZOOM_LEVEL = 10.0
|
|
571
|
-
val DEFAULT_MAX_ZOOM_LEVEL = 20.0
|
|
572
|
-
var offlineManager: OfflineManager? = null
|
|
573
|
-
var _tileStore: TileStore? = null
|
|
574
|
-
fun getOfflineManager(mReactContext: ReactApplicationContext?): OfflineManager {
|
|
575
|
-
val manager = offlineManager
|
|
576
|
-
if (manager == null) {
|
|
577
|
-
val result = OfflineManager(
|
|
578
|
-
ResourceOptions.Builder()
|
|
579
|
-
.accessToken(RCTMGLModule.getAccessToken(mReactContext)).tileStore(
|
|
580
|
-
getTileStore()
|
|
581
|
-
).build()
|
|
582
|
-
)
|
|
583
|
-
offlineManager = result
|
|
584
|
-
return result
|
|
585
|
-
} else {
|
|
586
|
-
return manager
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
669
|
|
|
590
|
-
fun getTileStore(): TileStore {
|
|
591
|
-
val store = _tileStore
|
|
592
|
-
if (store == null) {
|
|
593
|
-
val result = TileStore.create()
|
|
594
|
-
_tileStore = result
|
|
595
|
-
return result
|
|
596
|
-
}
|
|
597
|
-
return store
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
}
|