Send location uncertainty within a geo uri (#1309)

* Add uncertainty

* Add UTs

* Delete verticalAccuracy
This commit is contained in:
Alfonso Grillo 2023-07-12 11:02:05 +02:00 committed by GitHub
parent c573892954
commit adb253ff66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 11 deletions

View File

@ -58,6 +58,9 @@ struct MapLibreMapView: UIViewRepresentable {
@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
var userDidPan: (() -> Void)?
@ -155,6 +158,7 @@ extension MapLibreMapView {
}
previousUserLocation = userLocation
updateGeolocationUncertainty(location: userLocation)
}
func mapView(_ mapView: MGLMapView, didChangeLocationManagerAuthorization manager: MGLLocationManager) {
@ -177,12 +181,6 @@ extension MapLibreMapView {
}
}
// MARK: Callout
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
false
}
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.
switch reason {
@ -203,6 +201,23 @@ extension MapLibreMapView {
}
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
}
}
}

View File

@ -109,6 +109,7 @@ struct StaticLocationScreenViewState: BindableState {
struct StaticLocationScreenBindings {
var mapCenterLocation: CLLocationCoordinate2D?
var geolocationUncertainty: CLLocationAccuracy?
var showsUserLocationMode: ShowUserLocationMode

View File

@ -36,7 +36,8 @@ class StaticLocationScreenViewModel: StaticLocationScreenViewModelType, StaticLo
actionsSubject.send(.close)
case .selectLocation:
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:
state.bindings.showsUserLocationMode = .show
case .centerToUser:

View File

@ -47,10 +47,12 @@ struct StaticLocationScreen: View {
showsUserLocationMode: $context.showsUserLocationMode,
error: $context.mapError,
mapCenterCoordinate: $context.mapCenterLocation,
isLocationAuthorized: $context.isLocationAuthorized) {
isLocationAuthorized: $context.isLocationAuthorized,
geolocationUncertainty: $context.geolocationUncertainty) {
context.send(viewAction: .userDidPan)
}
.ignoresSafeArea(.all, edges: mapSafeAreaEdges)
if context.viewState.isLocationPickerMode {
LocationMarkerView()
}

View File

@ -78,8 +78,8 @@ private extension RegexGeoURI {
}
extension GeoURI {
init(coordinate: CLLocationCoordinate2D) {
self.init(latitude: coordinate.latitude, longitude: coordinate.longitude)
init(coordinate: CLLocationCoordinate2D, uncertainty: CLLocationAccuracy?) {
self.init(latitude: coordinate.latitude, longitude: coordinate.longitude, uncertainty: uncertainty)
}
}

View File

@ -76,4 +76,31 @@ class StaticLocationScreenViewModelTests: XCTestCase {
let authorizationError = AlertInfo(locationSharingViewError: .missingAuthorization)
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)
}
}