mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Move the interactive map into a new MapLibreShim framework
Second step towards loading MapLibre on demand: everything that touches it now lives in one framework, so that framework can later be left unlinked. The interactive map view, its annotation view and the coordinate animator move into MapLibreShim, which reaches the app through MapLibreShimProtocol. The app side keeps its MapLibreMapView call site and becomes a thin wrapper that builds a MapViewConfiguration, passing the app-only pieces (map style URLs, marker views, tint colour) across as closures so the shim needs nothing from the app. LocationAnnotation loses its MapLibre conformance and becomes a plain struct, with the shim mapping it onto its own annotation type. MapLibre's log forwarding moves into the shim as well, since TargetConfiguration can no longer reach it.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Copyright 2026 Element Creations Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Implemented by MapLibreShim's entry point, which the app instantiates after
|
||||
/// `dlopen`-ing the framework.
|
||||
public protocol MapLibreShimProtocol {
|
||||
/// Routes MapLibre's logs into the app's logger. Call once after loading the shim.
|
||||
func configureLogging(_ handler: @escaping @Sendable (MapLogSeverity, String) -> Void)
|
||||
|
||||
/// Builds the interactive map view. The app-side `MapLibreMapView` forwards every
|
||||
/// body evaluation here so SwiftUI updates flow through to the underlying map.
|
||||
func makeMapView(configuration: MapViewConfiguration) -> AnyView
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import CoreLocation
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
@@ -33,3 +34,23 @@ public enum MapLibreError: Error, Hashable {
|
||||
case failedLoadingMap
|
||||
case failedLocatingUser
|
||||
}
|
||||
|
||||
/// The severity of a map log message forwarded to the app.
|
||||
public enum MapLogSeverity {
|
||||
case error
|
||||
case warning
|
||||
case info
|
||||
case debug
|
||||
case verbose
|
||||
}
|
||||
|
||||
/// A marker shown on the map, identified so that it can be moved in place when its coordinate changes.
|
||||
public struct MapAnnotation {
|
||||
public let id: String
|
||||
public let coordinate: CLLocationCoordinate2D
|
||||
|
||||
public init(id: String, coordinate: CLLocationCoordinate2D) {
|
||||
self.id = id
|
||||
self.coordinate = coordinate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Copyright 2026 Element Creations Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import CoreLocation
|
||||
import SwiftUI
|
||||
|
||||
/// Everything the map implementation needs in order to render, expressed without app
|
||||
/// types so that the implementation framework can be loaded on demand.
|
||||
public struct MapViewConfiguration {
|
||||
/// the final zoom level used when the first user location emit
|
||||
public let zoomLevel: Double
|
||||
/// The initial zoom level used when the map it firstly loaded and the user location is not yet available, in case of annotations this property is not being used
|
||||
public let initialZoomLevel: Double
|
||||
|
||||
/// The initial map center
|
||||
public let mapCenter: CLLocationCoordinate2D
|
||||
|
||||
/// Map annotations
|
||||
public let annotations: [MapAnnotation]
|
||||
|
||||
/// The style to load the map with, for either the dark or the light appearance.
|
||||
public let styleURL: (_ isDark: Bool) -> URL?
|
||||
|
||||
public let tintColor: UIColor
|
||||
|
||||
/// The content of the marker representing the annotation with the given id.
|
||||
public let markerView: (_ annotationID: String) -> AnyView?
|
||||
|
||||
/// Behavior mode of the current user's location, can be hidden, only shown and shown following the user
|
||||
public let showsUserLocationMode: Binding<ShowUserLocationMode>
|
||||
/// Bind view errors if any
|
||||
public let error: Binding<MapLibreError?>
|
||||
/// Coordinate of the center of the map
|
||||
public let mapCenterCoordinate: Binding<CLLocationCoordinate2D?>
|
||||
public let hasLoadedUserLocation: Binding<Bool>
|
||||
public let isLocationAuthorized: Binding<Bool?>
|
||||
/// The radius of uncertainty for the location, measured in meters.
|
||||
public let geolocationUncertainty: Binding<CLLocationAccuracy?>
|
||||
|
||||
/// Called when the user pan on the map
|
||||
public let userDidPan: (() -> Void)?
|
||||
|
||||
public init(zoomLevel: Double,
|
||||
initialZoomLevel: Double,
|
||||
mapCenter: CLLocationCoordinate2D,
|
||||
annotations: [MapAnnotation] = [],
|
||||
styleURL: @escaping (_ isDark: Bool) -> URL?,
|
||||
tintColor: UIColor,
|
||||
markerView: @escaping (_ annotationID: String) -> AnyView?,
|
||||
showsUserLocationMode: Binding<ShowUserLocationMode>,
|
||||
error: Binding<MapLibreError?>,
|
||||
mapCenterCoordinate: Binding<CLLocationCoordinate2D?>,
|
||||
hasLoadedUserLocation: Binding<Bool>,
|
||||
isLocationAuthorized: Binding<Bool?>,
|
||||
geolocationUncertainty: Binding<CLLocationAccuracy?>,
|
||||
userDidPan: (() -> Void)? = nil) {
|
||||
self.zoomLevel = zoomLevel
|
||||
self.initialZoomLevel = initialZoomLevel
|
||||
self.mapCenter = mapCenter
|
||||
self.annotations = annotations
|
||||
self.styleURL = styleURL
|
||||
self.tintColor = tintColor
|
||||
self.markerView = markerView
|
||||
self.showsUserLocationMode = showsUserLocationMode
|
||||
self.error = error
|
||||
self.mapCenterCoordinate = mapCenterCoordinate
|
||||
self.hasLoadedUserLocation = hasLoadedUserLocation
|
||||
self.isLocationAuthorized = isLocationAuthorized
|
||||
self.geolocationUncertainty = geolocationUncertainty
|
||||
self.userDidPan = userDidPan
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user