Skip to content

Commit

Permalink
Merge pull request #59 from tappeddev/controller_reload_mapstatus_cal…
Browse files Browse the repository at this point in the history
…lback
  • Loading branch information
passsy authored Feb 7, 2024
2 parents 9e3a96c + d5a6c0f commit 1686dae
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 78 deletions.
1 change: 1 addition & 0 deletions arcgis_map_sdk/lib/arcgis_map_sdk.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ library arcgis_map;

export 'package:arcgis_map_sdk/src/arcgis_map_controller.dart';
export 'package:arcgis_map_sdk/src/arcgis_map_sdk.dart';
export 'package:arcgis_map_sdk/src/model/map_status.dart';
export 'package:arcgis_map_sdk_platform_interface/arcgis_map_sdk_platform_interface.dart';
45 changes: 44 additions & 1 deletion arcgis_map_sdk/lib/src/arcgis_map_controller.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import 'package:arcgis_map_sdk/src/model/map_status.dart';
import 'package:arcgis_map_sdk_platform_interface/arcgis_map_sdk_platform_interface.dart';
import 'package:flutter/services.dart';

typedef MapStatusListener = void Function(MapStatus status);

class ArcgisMapController {
ArcgisMapController._({
required this.mapId,
});
}) {
ArcgisMapPlatform.instance.setMethodCallHandler(
mapId: mapId,
onCall: _onCall,
);
}

final int mapId;

final _listeners = <MapStatusListener>[];
MapStatus _mapStatus = MapStatus.unknown;

MapStatus get mapStatus => _mapStatus;

static Future<ArcgisMapController> init(
int id,
) async {
Expand Down Expand Up @@ -60,6 +73,16 @@ class ArcgisMapController {
);
}

Future<void> _onCall(MethodCall call) async {
final method = call.method;
switch (method) {
case "onStatusChanged":
return _notifyStatusChanged(call);
default:
throw UnimplementedError('Method "$method" not implemented');
}
}

Stream<double> getZoom() {
return ArcgisMapPlatform.instance.getZoom(mapId);
}
Expand Down Expand Up @@ -160,6 +183,26 @@ class ArcgisMapController {
);
}

/// Adds a listener that gets notified if the map status changes.
VoidCallback addStatusChangeListener(MapStatusListener listener) {
_listeners.add(listener);
return () => _listeners.removeWhere((l) => l == listener);
}

/// Calling native `retryLoadAsync` (android) and `retryLoad` (swift)
/// https://developers.arcgis.com/kotlin/api-reference/arcgis-maps-kotlin/com.arcgismaps/-loadable/retry-load.html
/// This does not trigger `onMapCreated` since it will only try, if there is an error
Future<void> retryLoad() {
return ArcgisMapPlatform.instance.retryLoad(mapId);
}

void _notifyStatusChanged(MethodCall call) {
_mapStatus = MapStatus.values.byName(call.arguments as String);
for (final listener in _listeners) {
listener(_mapStatus);
}
}

Future<void> setInteraction({required bool isEnabled}) {
return ArcgisMapPlatform.instance
.setInteraction(mapId, isEnabled: isEnabled);
Expand Down
1 change: 1 addition & 0 deletions arcgis_map_sdk/lib/src/model/map_status.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
enum MapStatus { loaded, loading, failedToLoad, notLoaded, unknown }
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ import com.esri.arcgisruntime.geometry.PointCollection
import com.esri.arcgisruntime.geometry.Polyline
import com.esri.arcgisruntime.geometry.SpatialReferences
import com.esri.arcgisruntime.layers.ArcGISVectorTiledLayer
import com.esri.arcgisruntime.loadable.LoadStatus.FAILED_TO_LOAD
import com.esri.arcgisruntime.loadable.LoadStatus.LOADED
import com.esri.arcgisruntime.loadable.LoadStatus.LOADING
import com.esri.arcgisruntime.loadable.LoadStatus.NOT_LOADED
import com.esri.arcgisruntime.loadable.LoadStatusChangedEvent
import com.esri.arcgisruntime.mapping.ArcGISMap
import com.esri.arcgisruntime.mapping.Basemap
import com.esri.arcgisruntime.mapping.BasemapStyle
Expand Down Expand Up @@ -66,15 +71,20 @@ internal class ArcgisMapView(

mapView = view.findViewById(R.id.mapView)

if (mapOptions.basemap != null) {
map.basemap = Basemap(mapOptions.basemap)
} else {
val layers = mapOptions.vectorTilesUrls.map { url -> ArcGISVectorTiledLayer(url) }
map.basemap = Basemap(layers, null)
map.apply {

basemap = if (mapOptions.basemap != null) {
Basemap(mapOptions.basemap)
} else {
val layers = mapOptions.vectorTilesUrls.map { url -> ArcGISVectorTiledLayer(url) }
Basemap(layers, null)
}

minScale = getMapScale(mapOptions.minZoom)
maxScale = getMapScale(mapOptions.maxZoom)
addLoadStatusChangedListener(::onLoadStatusChanged)
}

map.minScale = getMapScale(mapOptions.minZoom)
map.maxScale = getMapScale(mapOptions.maxZoom)
mapView.map = map
mapView.graphicsOverlays.add(defaultGraphicsOverlay)

Expand Down Expand Up @@ -107,7 +117,15 @@ internal class ArcgisMapView(
setupEventChannel()
}

override fun dispose() {}
private fun onLoadStatusChanged(event: LoadStatusChangedEvent?) {
if (event == null) return
methodChannel.invokeMethod("onStatusChanged", event.jsonValue())
}

override fun dispose() {
map.removeLoadStatusChangedListener(::onLoadStatusChanged)
mapView.dispose()
}

// region helper

Expand All @@ -123,6 +141,7 @@ internal class ArcgisMapView(
"add_graphic" -> onAddGraphic(call = call, result = result)
"remove_graphic" -> onRemoveGraphic(call = call, result = result)
"toggle_base_map" -> onToggleBaseMap(call = call, result = result)
"retryLoad" -> onRetryLoad(result = result)
else -> result.notImplemented()
}
}
Expand Down Expand Up @@ -260,7 +279,7 @@ internal class ArcgisMapView(
val animationOptionMap = (arguments["animationOptions"] as Map<String, Any>?)

val animationOptions =
if (animationOptionMap == null || animationOptionMap.isEmpty()) null
if (animationOptionMap.isNullOrEmpty()) null
else animationOptionMap.parseToClass<AnimationOptions>()

val scale = if (zoomLevel != null) {
Expand Down Expand Up @@ -318,6 +337,11 @@ internal class ArcgisMapView(
result.success(true)
}

private fun onRetryLoad(result: MethodChannel.Result) {
mapView.map?.retryLoadAsync()
result.success(true)
}

/**
* Convert map scale to zoom level
* https://developers.arcgis.com/documentation/mapping-apis-and-services/reference/zoom-levels-and-scale/#conversion-tool
Expand Down Expand Up @@ -363,4 +387,11 @@ internal class ArcgisMapView(
// endregion
}

private fun LoadStatusChangedEvent.jsonValue() = when (newLoadStatus) {
LOADED -> "loaded"
LOADING -> "loading"
FAILED_TO_LOAD -> "failedToLoad"
NOT_LOADED -> "notLoaded"
else -> "unknown"
}

44 changes: 41 additions & 3 deletions arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
private let centerPositionEventChannel: FlutterEventChannel
private let centerPositionStreamHandler = CenterPositionStreamHandler()

private var mapLoadStatusObservation: NSKeyValueObservation?

private var mapScaleObservation: NSKeyValueObservation?
private var mapVisibleAreaObservation: NSKeyValueObservation?

Expand Down Expand Up @@ -115,6 +117,13 @@ class ArcgisMapView: NSObject, FlutterPlatformView {

setMapInteractive(mapOptions.isInteractive)
setupMethodChannel()

mapLoadStatusObservation = map.observe(\.loadStatus, options: .initial) { [weak self] (map, notifier) in
DispatchQueue.main.async {
let status = map.loadStatus
self?.notifyStatus(status)
}
}
}

private func setupMethodChannel() {
Expand All @@ -129,6 +138,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
case "add_graphic": onAddGraphic(call, result)
case "remove_graphic": onRemoveGraphic(call, result)
case "toggle_base_map" : onToggleBaseMap(call, result)
case "retryLoad" : onRetryLoad(call, result)
default:
result(FlutterError(code: "Unimplemented", message: "No method matching the name \(call.method)", details: nil))
}
Expand Down Expand Up @@ -203,10 +213,10 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
result(success)
}
}

private func onMoveCameraToPoints(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
let dict = call.arguments as! Dictionary<String, Any>

let payload: MoveToPointsPayload = try! JsonUtil.objectOfJson(dict)
let polyline = AGSPolyline(points: payload.points.map { latLng in AGSPoint(x: latLng.longitude, y:latLng.latitude, spatialReference: .wgs84()) })

Expand Down Expand Up @@ -280,7 +290,16 @@ class ArcgisMapView: NSObject, FlutterPlatformView {

result(true)
}


private func onRetryLoad(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
mapView.map!.retryLoad()
result(true)
}

private func notifyStatus(_ status: AGSLoadStatus) {
methodChannel.invokeMethod("onStatusChanged", arguments: status.jsonValue())
}

private func onSetInteraction(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
let enabled = (call.arguments! as! Dictionary<String, Any>)["enabled"]! as! Bool

Expand Down Expand Up @@ -479,6 +498,25 @@ extension AGSBasemapStyle {
}
}

extension AGSLoadStatus {
func jsonValue() -> String {
switch self {
case .loaded:
return "loaded"
case .loading:
return "loading"
case .failedToLoad:
return "failedToLoad"
case .notLoaded:
return "notLoaded"
case .unknown:
return "unknown"
@unknown default:
return "unknown"
}
}
}

struct MoveToPointsPayload : Codable {
let points : [LatLng]
let padding : Double?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,19 @@ class MethodChannelArcgisMapPlugin extends ArcgisMapPlatform {
).then((value) => value!);
}

@override
Future<void> retryLoad(int mapId) async {
return _methodChannelBuilder(mapId).invokeMethod("retryLoad");
}

@override
Future<void> setMethodCallHandler({
required int mapId,
required Future<dynamic> Function(MethodCall) onCall,
}) async {
return _methodChannelBuilder(mapId).setMethodCallHandler(onCall);
}

@override
Stream<double> getZoom(int mapId) {
_zoomEventStream ??=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,19 @@ class ArcgisMapPlatform extends PlatformInterface {
throw UnimplementedError('zoomOut() has not been implemented.');
}

Future<void> retryLoad(int mapId) {
throw UnimplementedError('reload() has not been implemented.');
}

Future<void> setMethodCallHandler({
required int mapId,
required Future<dynamic> Function(MethodCall) onCall,
}) {
throw UnimplementedError(
'setMethodCallHandler() has not been implemented.',
);
}

Future<void> setInteraction(int mapId, {required bool isEnabled}) {
throw UnimplementedError('setInteraction() has not been implemented.');
}
Expand Down
2 changes: 1 addition & 1 deletion example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: cc1f88378b4bfcf93a6ce00d2c587857c6008d3b

COCOAPODS: 1.14.2
COCOAPODS: 1.15.0
Loading

0 comments on commit 1686dae

Please sign in to comment.