mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Send location uncertainty within a geo uri (#1309)
* Add uncertainty * Add UTs * Delete verticalAccuracy
This commit is contained in:
@@ -57,6 +57,9 @@ struct MapLibreMapView: UIViewRepresentable {
|
|||||||
@Binding var mapCenterCoordinate: CLLocationCoordinate2D?
|
@Binding var mapCenterCoordinate: CLLocationCoordinate2D?
|
||||||
|
|
||||||
@Binding var isLocationAuthorized: Bool?
|
@Binding var isLocationAuthorized: Bool?
|
||||||
|
|
||||||
|
// The radius of uncertainty for the location, measured in meters.
|
||||||
|
@Binding var geolocationUncertainty: CLLocationAccuracy?
|
||||||
|
|
||||||
/// Called when the user pan on the map
|
/// Called when the user pan on the map
|
||||||
var userDidPan: (() -> Void)?
|
var userDidPan: (() -> Void)?
|
||||||
@@ -155,6 +158,7 @@ extension MapLibreMapView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
previousUserLocation = userLocation
|
previousUserLocation = userLocation
|
||||||
|
updateGeolocationUncertainty(location: userLocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapView(_ mapView: MGLMapView, didChangeLocationManagerAuthorization manager: MGLLocationManager) {
|
func mapView(_ mapView: MGLMapView, didChangeLocationManagerAuthorization manager: MGLLocationManager) {
|
||||||
@@ -176,13 +180,7 @@ extension MapLibreMapView {
|
|||||||
mapLibreView.mapCenterCoordinate = mapView.centerCoordinate
|
mapLibreView.mapCenterCoordinate = mapView.centerCoordinate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Callout
|
|
||||||
|
|
||||||
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera, reason: MGLCameraChangeReason) -> Bool {
|
func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera, reason: MGLCameraChangeReason) -> Bool {
|
||||||
// we send the userDidPan event only for the reasons that actually will change the map center, and not zoom only / rotations only events.
|
// we send the userDidPan event only for the reasons that actually will change the map center, and not zoom only / rotations only events.
|
||||||
switch reason {
|
switch reason {
|
||||||
@@ -203,6 +201,23 @@ extension MapLibreMapView {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Callout
|
||||||
|
|
||||||
|
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Private
|
||||||
|
|
||||||
|
private func updateGeolocationUncertainty(location: MGLUserLocation) {
|
||||||
|
guard let clLocation = location.location, clLocation.horizontalAccuracy >= 0 else {
|
||||||
|
mapLibreView.geolocationUncertainty = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mapLibreView.geolocationUncertainty = clLocation.horizontalAccuracy
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ struct StaticLocationScreenViewState: BindableState {
|
|||||||
|
|
||||||
struct StaticLocationScreenBindings {
|
struct StaticLocationScreenBindings {
|
||||||
var mapCenterLocation: CLLocationCoordinate2D?
|
var mapCenterLocation: CLLocationCoordinate2D?
|
||||||
|
var geolocationUncertainty: CLLocationAccuracy?
|
||||||
|
|
||||||
var showsUserLocationMode: ShowUserLocationMode
|
var showsUserLocationMode: ShowUserLocationMode
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ class StaticLocationScreenViewModel: StaticLocationScreenViewModelType, StaticLo
|
|||||||
actionsSubject.send(.close)
|
actionsSubject.send(.close)
|
||||||
case .selectLocation:
|
case .selectLocation:
|
||||||
guard let coordinate = state.bindings.mapCenterLocation else { return }
|
guard let coordinate = state.bindings.mapCenterLocation else { return }
|
||||||
actionsSubject.send(.sendLocation(.init(coordinate: coordinate), isUserLocation: state.isSharingUserLocation))
|
let uncertainty = state.isSharingUserLocation ? context.geolocationUncertainty : nil
|
||||||
|
actionsSubject.send(.sendLocation(.init(coordinate: coordinate, uncertainty: uncertainty), isUserLocation: state.isSharingUserLocation))
|
||||||
case .userDidPan:
|
case .userDidPan:
|
||||||
state.bindings.showsUserLocationMode = .show
|
state.bindings.showsUserLocationMode = .show
|
||||||
case .centerToUser:
|
case .centerToUser:
|
||||||
|
|||||||
@@ -47,10 +47,12 @@ struct StaticLocationScreen: View {
|
|||||||
showsUserLocationMode: $context.showsUserLocationMode,
|
showsUserLocationMode: $context.showsUserLocationMode,
|
||||||
error: $context.mapError,
|
error: $context.mapError,
|
||||||
mapCenterCoordinate: $context.mapCenterLocation,
|
mapCenterCoordinate: $context.mapCenterLocation,
|
||||||
isLocationAuthorized: $context.isLocationAuthorized) {
|
isLocationAuthorized: $context.isLocationAuthorized,
|
||||||
|
geolocationUncertainty: $context.geolocationUncertainty) {
|
||||||
context.send(viewAction: .userDidPan)
|
context.send(viewAction: .userDidPan)
|
||||||
}
|
}
|
||||||
.ignoresSafeArea(.all, edges: mapSafeAreaEdges)
|
.ignoresSafeArea(.all, edges: mapSafeAreaEdges)
|
||||||
|
|
||||||
if context.viewState.isLocationPickerMode {
|
if context.viewState.isLocationPickerMode {
|
||||||
LocationMarkerView()
|
LocationMarkerView()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ private extension RegexGeoURI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension GeoURI {
|
extension GeoURI {
|
||||||
init(coordinate: CLLocationCoordinate2D) {
|
init(coordinate: CLLocationCoordinate2D, uncertainty: CLLocationAccuracy?) {
|
||||||
self.init(latitude: coordinate.latitude, longitude: coordinate.longitude)
|
self.init(latitude: coordinate.latitude, longitude: coordinate.longitude, uncertainty: uncertainty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,4 +76,31 @@ class StaticLocationScreenViewModelTests: XCTestCase {
|
|||||||
let authorizationError = AlertInfo(locationSharingViewError: .missingAuthorization)
|
let authorizationError = AlertInfo(locationSharingViewError: .missingAuthorization)
|
||||||
XCTAssertEqual(authorizationError.message, L10n.errorMissingLocationAuth(InfoPlistReader.main.bundleDisplayName))
|
XCTAssertEqual(authorizationError.message, L10n.errorMissingLocationAuth(InfoPlistReader.main.bundleDisplayName))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testSendUserLocation() async throws {
|
||||||
|
context.mapCenterLocation = .init(latitude: 0, longitude: 0)
|
||||||
|
context.geolocationUncertainty = 10
|
||||||
|
let deferred = deferFulfillment(viewModel.actions.first())
|
||||||
|
context.send(viewAction: .selectLocation)
|
||||||
|
guard case .sendLocation(let geoUri, let isUserLocation) = try await deferred.fulfill() else {
|
||||||
|
XCTFail("Sent action should be 'sendLocation'")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
XCTAssertEqual(geoUri.uncertainty, 10)
|
||||||
|
XCTAssertTrue(isUserLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSendPickedLocation() async throws {
|
||||||
|
context.mapCenterLocation = .init(latitude: 0, longitude: 0)
|
||||||
|
context.isLocationAuthorized = nil
|
||||||
|
context.geolocationUncertainty = 10
|
||||||
|
let deferred = deferFulfillment(viewModel.actions.first())
|
||||||
|
context.send(viewAction: .selectLocation)
|
||||||
|
guard case .sendLocation(let geoUri, let isUserLocation) = try await deferred.fulfill() else {
|
||||||
|
XCTFail("Sent action should be 'sendLocation'")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
XCTAssertEqual(geoUri.uncertainty, nil)
|
||||||
|
XCTAssertFalse(isUserLocation)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user