expo-arcgis 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +144 -0
- package/android/build.gradle +39 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/expo/modules/arcgis/AnalysisOverlayRef.kt +165 -0
- package/android/src/main/java/expo/modules/arcgis/AuthChallengeHandler.kt +78 -0
- package/android/src/main/java/expo/modules/arcgis/CoordinateFormatterFunctions.kt +44 -0
- package/android/src/main/java/expo/modules/arcgis/DynamicEntityLayerRef.kt +133 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisGeometryModule.kt +119 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisMapView.kt +237 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisModule.kt +458 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisSceneView.kt +174 -0
- package/android/src/main/java/expo/modules/arcgis/GeocoderFunctions.kt +71 -0
- package/android/src/main/java/expo/modules/arcgis/GeometryCodec.kt +194 -0
- package/android/src/main/java/expo/modules/arcgis/GeometryEditorRef.kt +76 -0
- package/android/src/main/java/expo/modules/arcgis/GeometryEngineFunctions.kt +223 -0
- package/android/src/main/java/expo/modules/arcgis/GeoprocessingFunctions.kt +84 -0
- package/android/src/main/java/expo/modules/arcgis/GraphicsOverlayRef.kt +280 -0
- package/android/src/main/java/expo/modules/arcgis/JobRef.kt +41 -0
- package/android/src/main/java/expo/modules/arcgis/LayerRef.kt +261 -0
- package/android/src/main/java/expo/modules/arcgis/MapRef.kt +93 -0
- package/android/src/main/java/expo/modules/arcgis/OfflineFunctions.kt +171 -0
- package/android/src/main/java/expo/modules/arcgis/QueryCodec.kt +111 -0
- package/android/src/main/java/expo/modules/arcgis/RouterFunctions.kt +100 -0
- package/android/src/main/java/expo/modules/arcgis/SceneRef.kt +109 -0
- package/android/src/main/java/expo/modules/arcgis/UtilityNetworkRef.kt +198 -0
- package/app.plugin.js +3 -0
- package/build/AnalysisOverlay.d.ts +9 -0
- package/build/AnalysisOverlay.d.ts.map +1 -0
- package/build/AnalysisOverlay.js +30 -0
- package/build/AnalysisOverlay.js.map +1 -0
- package/build/DistanceMeasurement.d.ts +8 -0
- package/build/DistanceMeasurement.d.ts.map +1 -0
- package/build/DistanceMeasurement.js +47 -0
- package/build/DistanceMeasurement.js.map +1 -0
- package/build/DynamicEntityLayer.d.ts +18 -0
- package/build/DynamicEntityLayer.d.ts.map +1 -0
- package/build/DynamicEntityLayer.js +50 -0
- package/build/DynamicEntityLayer.js.map +1 -0
- package/build/ExpoArcgis.types.d.ts +1090 -0
- package/build/ExpoArcgis.types.d.ts.map +1 -0
- package/build/ExpoArcgis.types.js +2 -0
- package/build/ExpoArcgis.types.js.map +1 -0
- package/build/ExpoArcgisGeometryModule.d.ts +75 -0
- package/build/ExpoArcgisGeometryModule.d.ts.map +1 -0
- package/build/ExpoArcgisGeometryModule.js +3 -0
- package/build/ExpoArcgisGeometryModule.js.map +1 -0
- package/build/ExpoArcgisModule.d.ts +202 -0
- package/build/ExpoArcgisModule.d.ts.map +1 -0
- package/build/ExpoArcgisModule.js +3 -0
- package/build/ExpoArcgisModule.js.map +1 -0
- package/build/ExpoArcgisModule.web.d.ts +39 -0
- package/build/ExpoArcgisModule.web.d.ts.map +1 -0
- package/build/ExpoArcgisModule.web.js +38 -0
- package/build/ExpoArcgisModule.web.js.map +1 -0
- package/build/FeatureLayer.d.ts +14 -0
- package/build/FeatureLayer.d.ts.map +1 -0
- package/build/FeatureLayer.js +42 -0
- package/build/FeatureLayer.js.map +1 -0
- package/build/GeometryEditor.d.ts +11 -0
- package/build/GeometryEditor.d.ts.map +1 -0
- package/build/GeometryEditor.js +58 -0
- package/build/GeometryEditor.js.map +1 -0
- package/build/Graphic.d.ts +4 -0
- package/build/Graphic.d.ts.map +1 -0
- package/build/Graphic.js +36 -0
- package/build/Graphic.js.map +1 -0
- package/build/GraphicsOverlay.d.ts +12 -0
- package/build/GraphicsOverlay.d.ts.map +1 -0
- package/build/GraphicsOverlay.js +29 -0
- package/build/GraphicsOverlay.js.map +1 -0
- package/build/LineOfSight.d.ts +8 -0
- package/build/LineOfSight.d.ts.map +1 -0
- package/build/LineOfSight.js +50 -0
- package/build/LineOfSight.js.map +1 -0
- package/build/Map.d.ts +8 -0
- package/build/Map.d.ts.map +1 -0
- package/build/Map.js +34 -0
- package/build/Map.js.map +1 -0
- package/build/MapImageLayer.d.ts +4 -0
- package/build/MapImageLayer.d.ts.map +1 -0
- package/build/MapImageLayer.js +36 -0
- package/build/MapImageLayer.js.map +1 -0
- package/build/MapSettings.d.ts +17 -0
- package/build/MapSettings.d.ts.map +1 -0
- package/build/MapSettings.js +20 -0
- package/build/MapSettings.js.map +1 -0
- package/build/MapView.d.ts +10 -0
- package/build/MapView.d.ts.map +1 -0
- package/build/MapView.js +30 -0
- package/build/MapView.js.map +1 -0
- package/build/MapView.web.d.ts +4 -0
- package/build/MapView.web.d.ts.map +1 -0
- package/build/MapView.web.js +5 -0
- package/build/MapView.web.js.map +1 -0
- package/build/Scene.d.ts +8 -0
- package/build/Scene.d.ts.map +1 -0
- package/build/Scene.js +33 -0
- package/build/Scene.js.map +1 -0
- package/build/SceneLayer.d.ts +4 -0
- package/build/SceneLayer.d.ts.map +1 -0
- package/build/SceneLayer.js +36 -0
- package/build/SceneLayer.js.map +1 -0
- package/build/SceneView.d.ts +10 -0
- package/build/SceneView.d.ts.map +1 -0
- package/build/SceneView.js +29 -0
- package/build/SceneView.js.map +1 -0
- package/build/SceneView.web.d.ts +4 -0
- package/build/SceneView.web.d.ts.map +1 -0
- package/build/SceneView.web.js +5 -0
- package/build/SceneView.web.js.map +1 -0
- package/build/TileLayer.d.ts +4 -0
- package/build/TileLayer.d.ts.map +1 -0
- package/build/TileLayer.js +36 -0
- package/build/TileLayer.js.map +1 -0
- package/build/UtilityNetwork.d.ts +8 -0
- package/build/UtilityNetwork.d.ts.map +1 -0
- package/build/UtilityNetwork.js +38 -0
- package/build/UtilityNetwork.js.map +1 -0
- package/build/Viewshed.d.ts +7 -0
- package/build/Viewshed.d.ts.map +1 -0
- package/build/Viewshed.js +39 -0
- package/build/Viewshed.js.map +1 -0
- package/build/auth.d.ts +36 -0
- package/build/auth.d.ts.map +1 -0
- package/build/auth.js +47 -0
- package/build/auth.js.map +1 -0
- package/build/contexts.d.ts +34 -0
- package/build/contexts.d.ts.map +1 -0
- package/build/contexts.js +42 -0
- package/build/contexts.js.map +1 -0
- package/build/coordinateFormatter.d.ts +26 -0
- package/build/coordinateFormatter.d.ts.map +1 -0
- package/build/coordinateFormatter.js +26 -0
- package/build/coordinateFormatter.js.map +1 -0
- package/build/createLayerComponent.d.ts +8 -0
- package/build/createLayerComponent.d.ts.map +1 -0
- package/build/createLayerComponent.js +41 -0
- package/build/createLayerComponent.js.map +1 -0
- package/build/geocoder.d.ts +16 -0
- package/build/geocoder.d.ts.map +1 -0
- package/build/geocoder.js +16 -0
- package/build/geocoder.js.map +1 -0
- package/build/geometryEngine.d.ts +87 -0
- package/build/geometryEngine.d.ts.map +1 -0
- package/build/geometryEngine.js +87 -0
- package/build/geometryEngine.js.map +1 -0
- package/build/geoprocessor.d.ts +13 -0
- package/build/geoprocessor.d.ts.map +1 -0
- package/build/geoprocessor.js +12 -0
- package/build/geoprocessor.js.map +1 -0
- package/build/hooks/usePrevious.d.ts +4 -0
- package/build/hooks/usePrevious.d.ts.map +1 -0
- package/build/hooks/usePrevious.js +11 -0
- package/build/hooks/usePrevious.js.map +1 -0
- package/build/hooks/useUpdateEffect.d.ts +6 -0
- package/build/hooks/useUpdateEffect.d.ts.map +1 -0
- package/build/hooks/useUpdateEffect.js +16 -0
- package/build/hooks/useUpdateEffect.js.map +1 -0
- package/build/index.d.ts +31 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +31 -0
- package/build/index.js.map +1 -0
- package/build/layers.d.ts +26 -0
- package/build/layers.d.ts.map +1 -0
- package/build/layers.js +27 -0
- package/build/layers.js.map +1 -0
- package/build/offline.d.ts +44 -0
- package/build/offline.d.ts.map +1 -0
- package/build/offline.js +39 -0
- package/build/offline.js.map +1 -0
- package/build/router.d.ts +12 -0
- package/build/router.d.ts.map +1 -0
- package/build/router.js +12 -0
- package/build/router.js.map +1 -0
- package/build/utils/getPropsDiffs.d.ts +3 -0
- package/build/utils/getPropsDiffs.d.ts.map +1 -0
- package/build/utils/getPropsDiffs.js +23 -0
- package/build/utils/getPropsDiffs.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/ios/AnalysisOverlayRef.swift +184 -0
- package/ios/AuthChallengeHandler.swift +30 -0
- package/ios/CoordinateFormatterFunctions.swift +52 -0
- package/ios/DynamicEntityLayerRef.swift +136 -0
- package/ios/ExpoArcgis.podspec +35 -0
- package/ios/ExpoArcgisGeometryModule.swift +113 -0
- package/ios/ExpoArcgisMapView.swift +258 -0
- package/ios/ExpoArcgisModule.swift +488 -0
- package/ios/ExpoArcgisSceneView.swift +200 -0
- package/ios/GeocoderFunctions.swift +90 -0
- package/ios/GeometryCodec.swift +199 -0
- package/ios/GeometryEditorRef.swift +66 -0
- package/ios/GeometryEngineFunctions.swift +201 -0
- package/ios/GeoprocessingFunctions.swift +88 -0
- package/ios/GraphicsOverlayRef.swift +292 -0
- package/ios/JobRef.swift +37 -0
- package/ios/LayerRef.swift +258 -0
- package/ios/MapRef.swift +88 -0
- package/ios/OfflineFunctions.swift +132 -0
- package/ios/QueryCodec.swift +126 -0
- package/ios/RouterFunctions.swift +109 -0
- package/ios/SceneRef.swift +111 -0
- package/ios/UtilityNetworkRef.swift +182 -0
- package/package.json +75 -0
- package/src/AnalysisOverlay.tsx +37 -0
- package/src/DistanceMeasurement.tsx +58 -0
- package/src/DynamicEntityLayer.tsx +65 -0
- package/src/ExpoArcgis.types.ts +1248 -0
- package/src/ExpoArcgisGeometryModule.ts +140 -0
- package/src/ExpoArcgisModule.ts +258 -0
- package/src/ExpoArcgisModule.web.ts +46 -0
- package/src/FeatureLayer.tsx +50 -0
- package/src/GeometryEditor.tsx +68 -0
- package/src/Graphic.tsx +41 -0
- package/src/GraphicsOverlay.tsx +41 -0
- package/src/LineOfSight.tsx +55 -0
- package/src/Map.tsx +39 -0
- package/src/MapImageLayer.tsx +41 -0
- package/src/MapSettings.tsx +33 -0
- package/src/MapView.tsx +71 -0
- package/src/MapView.web.tsx +8 -0
- package/src/Scene.tsx +38 -0
- package/src/SceneLayer.tsx +41 -0
- package/src/SceneView.tsx +72 -0
- package/src/SceneView.web.tsx +8 -0
- package/src/TileLayer.tsx +41 -0
- package/src/UtilityNetwork.tsx +43 -0
- package/src/Viewshed.tsx +44 -0
- package/src/auth.ts +74 -0
- package/src/contexts.ts +76 -0
- package/src/coordinateFormatter.ts +62 -0
- package/src/createLayerComponent.tsx +46 -0
- package/src/geocoder.ts +29 -0
- package/src/geometryEngine.ts +162 -0
- package/src/geoprocessor.ts +17 -0
- package/src/hooks/usePrevious.ts +12 -0
- package/src/hooks/useUpdateEffect.ts +17 -0
- package/src/index.ts +60 -0
- package/src/layers.tsx +76 -0
- package/src/offline.ts +85 -0
- package/src/router.ts +14 -0
- package/src/utils/getPropsDiffs.ts +23 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
package expo.modules.arcgis
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.functions.Coroutine
|
|
4
|
+
import expo.modules.kotlin.modules.Module
|
|
5
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Second native module hosting the GeometryEngine + CoordinateFormatter operations, exposed to
|
|
9
|
+
* JS as `ExpoArcgisGeometry`. Split out of [ExpoArcgisModule] so that neither module's
|
|
10
|
+
* `definition()` exceeds the JVM 64 KB method-size limit.
|
|
11
|
+
*/
|
|
12
|
+
class ExpoArcgisGeometryModule : Module() {
|
|
13
|
+
override fun definition() = ModuleDefinition {
|
|
14
|
+
Name("ExpoArcgisGeometry")
|
|
15
|
+
|
|
16
|
+
// GeometryEngine — spatial operations exposed as the JS `geometryEngine` namespace.
|
|
17
|
+
Function("geProject", ::geProject)
|
|
18
|
+
Function("geBuffer", ::geBuffer)
|
|
19
|
+
Function("geGeodeticBuffer", ::geGeodeticBuffer)
|
|
20
|
+
Function("geArea", ::geArea)
|
|
21
|
+
Function("geGeodeticArea", ::geGeodeticArea)
|
|
22
|
+
Function("geLength", ::geLength)
|
|
23
|
+
Function("geGeodeticLength", ::geGeodeticLength)
|
|
24
|
+
Function("geDistance", ::geDistance)
|
|
25
|
+
Function("geGeodeticDistance", ::geGeodeticDistance)
|
|
26
|
+
Function("geUnion", ::geUnion)
|
|
27
|
+
Function("geIntersection", ::geIntersection)
|
|
28
|
+
Function("geDifference", ::geDifference)
|
|
29
|
+
Function("geSymmetricDifference", ::geSymmetricDifference)
|
|
30
|
+
Function("geClip", ::geClip)
|
|
31
|
+
Function("geCut", ::geCut)
|
|
32
|
+
Function("geConvexHull", ::geConvexHull)
|
|
33
|
+
Function("geBoundary", ::geBoundary)
|
|
34
|
+
Function("geSimplify", ::geSimplify)
|
|
35
|
+
Function("geDensify", ::geDensify)
|
|
36
|
+
Function("geGeneralize", ::geGeneralize)
|
|
37
|
+
Function("geOffset", ::geOffset)
|
|
38
|
+
Function("geCombineExtents", ::geCombineExtents)
|
|
39
|
+
Function("geContains", ::geContains)
|
|
40
|
+
Function("geCrosses", ::geCrosses)
|
|
41
|
+
Function("geDisjoint", ::geDisjoint)
|
|
42
|
+
Function("geEquals", ::geEquals)
|
|
43
|
+
Function("geIntersects", ::geIntersects)
|
|
44
|
+
Function("geOverlaps", ::geOverlaps)
|
|
45
|
+
Function("geTouches", ::geTouches)
|
|
46
|
+
Function("geWithin", ::geWithin)
|
|
47
|
+
Function("geRelate", ::geRelate)
|
|
48
|
+
Function("geIsSimple", ::geIsSimple)
|
|
49
|
+
Function("geNearestCoordinate", ::geNearestCoordinate)
|
|
50
|
+
Function("geNearestVertex", ::geNearestVertex)
|
|
51
|
+
Function("geMove", ::geMove)
|
|
52
|
+
Function("geRotate", ::geRotate)
|
|
53
|
+
Function("geScale", ::geScale)
|
|
54
|
+
|
|
55
|
+
// CoordinateFormatter — point <-> notation strings, exposed as the JS `coordinateFormatter` namespace.
|
|
56
|
+
Function("cfToLatLong", ::cfToLatLong)
|
|
57
|
+
Function("cfFromLatLong", ::cfFromLatLong)
|
|
58
|
+
Function("cfToMgrs", ::cfToMgrs)
|
|
59
|
+
Function("cfFromMgrs", ::cfFromMgrs)
|
|
60
|
+
Function("cfToUsng", ::cfToUsng)
|
|
61
|
+
Function("cfFromUsng", ::cfFromUsng)
|
|
62
|
+
Function("cfToUtm", ::cfToUtm)
|
|
63
|
+
Function("cfFromUtm", ::cfFromUtm)
|
|
64
|
+
|
|
65
|
+
// Geocoding — address <-> coordinates search, exposed as the JS `geocoder` namespace.
|
|
66
|
+
AsyncFunction("geocode") Coroutine { searchText: String, params: Map<String, Any?> ->
|
|
67
|
+
geocode(searchText, params)
|
|
68
|
+
}
|
|
69
|
+
AsyncFunction("reverseGeocode") Coroutine { point: Map<String, Any?>, params: Map<String, Any?> ->
|
|
70
|
+
reverseGeocode(point, params)
|
|
71
|
+
}
|
|
72
|
+
AsyncFunction("suggest") Coroutine { searchText: String, params: Map<String, Any?> ->
|
|
73
|
+
suggest(searchText, params)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Routing — solve a route between stops, exposed as the JS `router` namespace.
|
|
77
|
+
AsyncFunction("solveRoute") Coroutine { stops: List<Map<String, Any?>>, params: Map<String, Any?> ->
|
|
78
|
+
solveRoute(stops, params)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Geoprocessing — run a geoprocessing service, exposed as the JS `geoprocessor` namespace.
|
|
82
|
+
AsyncFunction("executeGeoprocessing") Coroutine { serviceUrl: String, inputs: Map<String, Any?> ->
|
|
83
|
+
executeGeoprocessing(appContext, serviceUrl, inputs)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Job handle for long-running downloads — emits onProgress, awaits via result(), supports cancel().
|
|
87
|
+
Class(JobRef::class) {
|
|
88
|
+
Events("onProgress")
|
|
89
|
+
AsyncFunction("result") Coroutine { ref: JobRef -> ref.result() }
|
|
90
|
+
AsyncFunction("cancel") Coroutine { ref: JobRef -> ref.cancel() }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Offline — take maps/data offline, exposed as the JS `offline` namespace.
|
|
94
|
+
AsyncFunction("generateOfflineMap") Coroutine { portalItemId: String, areaOfInterest: Map<String, Any?>, downloadName: String ->
|
|
95
|
+
generateOfflineMap(appContext, appContext.reactContext?.filesDir, portalItemId, areaOfInterest, downloadName)
|
|
96
|
+
}
|
|
97
|
+
AsyncFunction("syncOfflineMap") Coroutine { mobileMapPackagePath: String ->
|
|
98
|
+
syncOfflineMap(appContext, mobileMapPackagePath)
|
|
99
|
+
}
|
|
100
|
+
AsyncFunction("preplannedMapAreas") Coroutine { portalItemId: String ->
|
|
101
|
+
preplannedMapAreas(portalItemId)
|
|
102
|
+
}
|
|
103
|
+
AsyncFunction("downloadPreplannedOfflineMap") Coroutine { portalItemId: String, areaIndex: Int, downloadName: String ->
|
|
104
|
+
downloadPreplannedOfflineMap(appContext, appContext.reactContext?.filesDir, portalItemId, areaIndex, downloadName)
|
|
105
|
+
}
|
|
106
|
+
AsyncFunction("generateGeodatabase") Coroutine { featureServiceUrl: String, extent: Map<String, Any?>, downloadName: String ->
|
|
107
|
+
generateGeodatabase(appContext, appContext.reactContext?.filesDir, featureServiceUrl, extent, downloadName)
|
|
108
|
+
}
|
|
109
|
+
AsyncFunction("syncGeodatabase") Coroutine { geodatabasePath: String, featureServiceUrl: String ->
|
|
110
|
+
syncGeodatabase(appContext, geodatabasePath, featureServiceUrl)
|
|
111
|
+
}
|
|
112
|
+
AsyncFunction("exportTileCache") Coroutine { tileServiceUrl: String, areaOfInterest: Map<String, Any?>, downloadName: String ->
|
|
113
|
+
exportTileCache(appContext, appContext.reactContext?.filesDir, tileServiceUrl, areaOfInterest, downloadName)
|
|
114
|
+
}
|
|
115
|
+
AsyncFunction("exportVectorTiles") Coroutine { vectorTileServiceUrl: String, areaOfInterest: Map<String, Any?>, downloadName: String ->
|
|
116
|
+
exportVectorTiles(appContext, appContext.reactContext?.filesDir, vectorTileServiceUrl, areaOfInterest, downloadName)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
package expo.modules.arcgis
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.view.ViewGroup
|
|
5
|
+
import androidx.lifecycle.Lifecycle
|
|
6
|
+
import androidx.lifecycle.findViewTreeLifecycleOwner
|
|
7
|
+
import com.arcgismaps.geometry.GeometryEngine
|
|
8
|
+
import com.arcgismaps.geometry.Point
|
|
9
|
+
import com.arcgismaps.geometry.SpatialReference
|
|
10
|
+
import com.arcgismaps.geometry.Polyline
|
|
11
|
+
import com.arcgismaps.location.Location
|
|
12
|
+
import com.arcgismaps.location.LocationDataSource
|
|
13
|
+
import com.arcgismaps.location.LocationDisplayAutoPanMode
|
|
14
|
+
import com.arcgismaps.location.SimulatedLocationDataSource
|
|
15
|
+
import com.arcgismaps.location.SimulationParameters
|
|
16
|
+
import com.arcgismaps.location.SystemLocationDataSource
|
|
17
|
+
import java.time.Instant
|
|
18
|
+
import com.arcgismaps.mapping.Viewpoint
|
|
19
|
+
import com.arcgismaps.mapping.view.MapView
|
|
20
|
+
import com.arcgismaps.mapping.view.ScreenCoordinate
|
|
21
|
+
import expo.modules.kotlin.AppContext
|
|
22
|
+
import expo.modules.kotlin.Promise
|
|
23
|
+
import expo.modules.kotlin.records.Field
|
|
24
|
+
import expo.modules.kotlin.records.Record
|
|
25
|
+
import expo.modules.kotlin.viewevent.EventDispatcher
|
|
26
|
+
import expo.modules.kotlin.views.ExpoView
|
|
27
|
+
import kotlinx.coroutines.CoroutineScope
|
|
28
|
+
import kotlinx.coroutines.Dispatchers
|
|
29
|
+
import kotlinx.coroutines.Job
|
|
30
|
+
import kotlinx.coroutines.SupervisorJob
|
|
31
|
+
import kotlinx.coroutines.launch
|
|
32
|
+
|
|
33
|
+
class MapLoadedEventPayload(@Field val spatialReferenceWkid: Int? = null) : Record
|
|
34
|
+
class MapLoadErrorEventPayload(@Field val message: String = "") : Record
|
|
35
|
+
|
|
36
|
+
class PointRecord(
|
|
37
|
+
@Field val latitude: Double = 0.0,
|
|
38
|
+
@Field val longitude: Double = 0.0,
|
|
39
|
+
) : Record
|
|
40
|
+
|
|
41
|
+
class ScreenPointRecord(
|
|
42
|
+
@Field val x: Double = 0.0,
|
|
43
|
+
@Field val y: Double = 0.0,
|
|
44
|
+
) : Record
|
|
45
|
+
|
|
46
|
+
class TapEventPayload(
|
|
47
|
+
@Field val mapPoint: PointRecord = PointRecord(),
|
|
48
|
+
@Field val screenPoint: ScreenPointRecord = ScreenPointRecord(),
|
|
49
|
+
) : Record
|
|
50
|
+
|
|
51
|
+
class LocationPositionRecord(
|
|
52
|
+
@Field val latitude: Double = 0.0,
|
|
53
|
+
@Field val longitude: Double = 0.0,
|
|
54
|
+
@Field val z: Double? = null,
|
|
55
|
+
) : Record
|
|
56
|
+
|
|
57
|
+
class LocationEventPayload(
|
|
58
|
+
@Field val position: LocationPositionRecord = LocationPositionRecord(),
|
|
59
|
+
@Field val horizontalAccuracy: Double = 0.0,
|
|
60
|
+
@Field val verticalAccuracy: Double = 0.0,
|
|
61
|
+
@Field val course: Double = 0.0,
|
|
62
|
+
@Field val speed: Double = 0.0,
|
|
63
|
+
@Field val timestamp: Double = 0.0,
|
|
64
|
+
) : Record
|
|
65
|
+
|
|
66
|
+
/** Declarative 2D map host. Renders the [MapRef] passed as the `map` view prop. */
|
|
67
|
+
class ExpoArcgisMapView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
|
|
68
|
+
private val onMapLoaded by EventDispatcher<MapLoadedEventPayload>()
|
|
69
|
+
private val onMapLoadError by EventDispatcher<MapLoadErrorEventPayload>()
|
|
70
|
+
private val onTap by EventDispatcher<TapEventPayload>()
|
|
71
|
+
private val onLocationChange by EventDispatcher<LocationEventPayload>()
|
|
72
|
+
|
|
73
|
+
private val mapView = MapView(context).also {
|
|
74
|
+
it.layoutParams = ViewGroup.LayoutParams(
|
|
75
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
76
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
77
|
+
)
|
|
78
|
+
addView(it)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private val scope = CoroutineScope(Dispatchers.Main.immediate + SupervisorJob())
|
|
82
|
+
private var loadJob: Job? = null
|
|
83
|
+
private var observedLifecycle: Lifecycle? = null
|
|
84
|
+
|
|
85
|
+
init {
|
|
86
|
+
// Emit tap events with the map location (projected to WGS84).
|
|
87
|
+
scope.launch {
|
|
88
|
+
mapView.onSingleTapConfirmed.collect { event ->
|
|
89
|
+
val wgs84 = event.mapPoint?.let {
|
|
90
|
+
GeometryEngine.projectOrNull(it, SpatialReference.wgs84()) as? Point
|
|
91
|
+
}
|
|
92
|
+
onTap(
|
|
93
|
+
TapEventPayload(
|
|
94
|
+
mapPoint = PointRecord(wgs84?.y ?: 0.0, wgs84?.x ?: 0.0),
|
|
95
|
+
screenPoint = ScreenPointRecord(event.screenCoordinate.x, event.screenCoordinate.y)
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Emit a location event on each device-location update.
|
|
101
|
+
scope.launch {
|
|
102
|
+
mapView.locationDisplay.location.collect { location ->
|
|
103
|
+
location?.let { onLocationChange(locationPayload(it)) }
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Receives the native map (by reference) from the `<Map>` SharedObject. */
|
|
109
|
+
fun setMap(ref: MapRef?) {
|
|
110
|
+
ref ?: return
|
|
111
|
+
applyMap(ref.map)
|
|
112
|
+
// The map may be replaced asynchronously (e.g. once a mobile map package loads) — re-apply then.
|
|
113
|
+
ref.onMapChanged = { newMap -> applyMap(newMap) }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private fun applyMap(map: com.arcgismaps.mapping.ArcGISMap) {
|
|
117
|
+
mapView.map = map
|
|
118
|
+
loadJob?.cancel()
|
|
119
|
+
loadJob = scope.launch {
|
|
120
|
+
map.load()
|
|
121
|
+
.onSuccess { onMapLoaded(MapLoadedEventPayload()) }
|
|
122
|
+
.onFailure { error ->
|
|
123
|
+
onMapLoadError(MapLoadErrorEventPayload(error.message ?: "Failed to load map"))
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Receives the graphics overlays declared as `<GraphicsOverlay>` children of the `<MapView>`. */
|
|
129
|
+
fun setGraphicsOverlays(refs: List<GraphicsOverlayRef>) {
|
|
130
|
+
mapView.graphicsOverlays.clear()
|
|
131
|
+
mapView.graphicsOverlays.addAll(refs.map { it.overlay })
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Animates the view to a runtime viewpoint sent from JS. */
|
|
135
|
+
fun setViewpoint(vp: Map<String, Any?>?) {
|
|
136
|
+
vp ?: return
|
|
137
|
+
val lat = (vp["latitude"] as? Number)?.toDouble() ?: return
|
|
138
|
+
val lon = (vp["longitude"] as? Number)?.toDouble() ?: return
|
|
139
|
+
val scale = (vp["scale"] as? Number)?.toDouble() ?: return
|
|
140
|
+
scope.launch { mapView.setViewpointAnimated(Viewpoint(lat, lon, scale), 0.5f) }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Enables/configures the device location display from JS (null disables it). */
|
|
144
|
+
fun setLocationDisplay(config: Map<String, Any?>?) {
|
|
145
|
+
val locationDisplay = mapView.locationDisplay
|
|
146
|
+
if (config == null) {
|
|
147
|
+
scope.launch { locationDisplay.dataSource.stop() }
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
locationDisplay.setAutoPanMode(autoPanMode(config["autoPanMode"] as? String))
|
|
151
|
+
(config["showLocation"] as? Boolean)?.let { locationDisplay.showLocation = it }
|
|
152
|
+
(config["wanderExtentFactor"] as? Number)?.toFloat()?.let { locationDisplay.wanderExtentFactor = it }
|
|
153
|
+
val newSource = locationDataSource(config["source"])
|
|
154
|
+
scope.launch {
|
|
155
|
+
locationDisplay.dataSource.stop()
|
|
156
|
+
if (newSource != null) locationDisplay.dataSource = newSource
|
|
157
|
+
locationDisplay.dataSource.start()
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Resolves the JS `source` to a data source. Returns null to keep the current source unchanged. */
|
|
162
|
+
private fun locationDataSource(source: Any?): LocationDataSource? {
|
|
163
|
+
if (source is Map<*, *> && source["type"] == "simulated") {
|
|
164
|
+
val route = (source["route"] as? Map<*, *>)?.let { geometryFromDict(it) } as? Polyline ?: return null
|
|
165
|
+
val speed = (source["speed"] as? Number)?.toDouble() ?: 10.0
|
|
166
|
+
return SimulatedLocationDataSource(route, SimulationParameters(Instant.now(), speed, 0.0, 0.0))
|
|
167
|
+
}
|
|
168
|
+
// 'system' / unspecified: swap back only if currently simulated, otherwise keep the source.
|
|
169
|
+
return if (mapView.locationDisplay.dataSource is SimulatedLocationDataSource) SystemLocationDataSource() else null
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private fun locationPayload(location: Location): LocationEventPayload = LocationEventPayload(
|
|
173
|
+
position = LocationPositionRecord(location.position.y, location.position.x, location.position.z),
|
|
174
|
+
horizontalAccuracy = location.horizontalAccuracy,
|
|
175
|
+
verticalAccuracy = location.verticalAccuracy,
|
|
176
|
+
course = location.course,
|
|
177
|
+
speed = location.speed,
|
|
178
|
+
timestamp = location.timestamp.toEpochMilli().toDouble(),
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
/** Binds an interactive GeometryEditor for sketching (null clears it). */
|
|
182
|
+
fun setGeometryEditor(ref: GeometryEditorRef?) {
|
|
183
|
+
mapView.geometryEditor = ref?.editor
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Identifies the features under a screen point (one result per layer with hits). */
|
|
187
|
+
fun identify(screenPoint: Map<String, Any?>, options: Map<String, Any?>?, promise: Promise) {
|
|
188
|
+
val x = (screenPoint["x"] as? Number)?.toDouble() ?: 0.0
|
|
189
|
+
val y = (screenPoint["y"] as? Number)?.toDouble() ?: 0.0
|
|
190
|
+
val tolerance = (options?.get("tolerance") as? Number)?.toDouble() ?: 12.0
|
|
191
|
+
val maxResults = (options?.get("maxResults") as? Number)?.toInt() ?: 1
|
|
192
|
+
scope.launch {
|
|
193
|
+
mapView.identifyLayers(ScreenCoordinate(x, y), tolerance, false, maxResults)
|
|
194
|
+
.onSuccess { results -> promise.resolve(results.map { serializeIdentifyResult(it) }) }
|
|
195
|
+
.onFailure { promise.reject("IDENTIFY_ERROR", it.message ?: "Identify failed", it) }
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Retries loading the map (Loadable pattern) — useful after a network outage. Re-emits the result. */
|
|
200
|
+
fun retryLoad(promise: Promise) {
|
|
201
|
+
val map = mapView.map ?: run { promise.resolve(null); return }
|
|
202
|
+
scope.launch {
|
|
203
|
+
map.retryLoad()
|
|
204
|
+
.onSuccess { onMapLoaded(MapLoadedEventPayload()); promise.resolve(null) }
|
|
205
|
+
.onFailure { error ->
|
|
206
|
+
onMapLoadError(MapLoadErrorEventPayload(error.message ?: "Failed to load map"))
|
|
207
|
+
promise.resolve(null)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
override fun onAttachedToWindow() {
|
|
213
|
+
super.onAttachedToWindow()
|
|
214
|
+
// The view-based MapView renders only while observing a lifecycle.
|
|
215
|
+
val lifecycle = findViewTreeLifecycleOwner()?.lifecycle
|
|
216
|
+
if (lifecycle != null && lifecycle !== observedLifecycle) {
|
|
217
|
+
observedLifecycle?.removeObserver(mapView)
|
|
218
|
+
lifecycle.addObserver(mapView)
|
|
219
|
+
observedLifecycle = lifecycle
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
override fun onDetachedFromWindow() {
|
|
224
|
+
super.onDetachedFromWindow()
|
|
225
|
+
loadJob?.cancel()
|
|
226
|
+
observedLifecycle?.removeObserver(mapView)
|
|
227
|
+
observedLifecycle = null
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Maps the JS auto-pan union to the native [LocationDisplayAutoPanMode]. */
|
|
232
|
+
private fun autoPanMode(mode: String?): LocationDisplayAutoPanMode = when (mode) {
|
|
233
|
+
"recenter" -> LocationDisplayAutoPanMode.Recenter
|
|
234
|
+
"navigation" -> LocationDisplayAutoPanMode.Navigation
|
|
235
|
+
"compassNavigation" -> LocationDisplayAutoPanMode.CompassNavigation
|
|
236
|
+
else -> LocationDisplayAutoPanMode.Off
|
|
237
|
+
}
|