mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Refactor and redesign Location Sharing Screen (#5155)
* refactored the static location screen to the location sharing screen # Conflicts: # UnitTests/Sources/LocationSharingScreenViewModelTests.swift # Conflicts: # ElementX.xcodeproj/project.pbxproj * implemented a custom pin with an overlayable view * implemented the render of the user when the location is sender instead of the pin type * removed description and body they are not used at all. * reimplemented single button for sharing this or user location + implemented an experimental way to update annotations * removed unnecessary @Suite description * implemented a way to display the alert on top of the sheet and added a spinner to the center user location button * fixed alerts strings * fixed a failing test * improved preview tests
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Copyright 2025 Element Creations Ltd.
|
||||
// Copyright 2023-2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Combine
|
||||
@testable import ElementX
|
||||
import Testing
|
||||
|
||||
@MainActor
|
||||
struct LocationSharingScreenViewModelTests {
|
||||
private let timelineProxy = TimelineProxyMock(.init())
|
||||
private var viewModel: LocationSharingScreenViewModelProtocol
|
||||
|
||||
private var context: LocationSharingScreenViewModel.Context {
|
||||
viewModel.context
|
||||
}
|
||||
|
||||
init() {
|
||||
let viewModel = LocationSharingScreenViewModel(interactionMode: .picker,
|
||||
mapURLBuilder: ServiceLocator.shared.settings.mapTilerConfiguration,
|
||||
liveLocationSharingEnabled: true,
|
||||
roomProxy: JoinedRoomProxyMock(.init()),
|
||||
timelineController: MockTimelineController(timelineProxy: timelineProxy),
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
mediaProvider: MediaProviderMock(configuration: .init()))
|
||||
viewModel.state.bindings.isLocationAuthorized = true
|
||||
self.viewModel = viewModel
|
||||
}
|
||||
|
||||
@Test
|
||||
func userDidPan() {
|
||||
#expect(context.viewState.isSharingUserLocation)
|
||||
#expect(context.showsUserLocationMode == .showAndFollow)
|
||||
context.send(viewAction: .userDidPan)
|
||||
#expect(!context.viewState.isSharingUserLocation)
|
||||
#expect(context.showsUserLocationMode == .show)
|
||||
}
|
||||
|
||||
@Test
|
||||
func centerOnUser() {
|
||||
#expect(context.viewState.isSharingUserLocation)
|
||||
context.showsUserLocationMode = .show
|
||||
#expect(!context.viewState.isSharingUserLocation)
|
||||
context.send(viewAction: .centerToUser)
|
||||
#expect(context.viewState.isSharingUserLocation)
|
||||
#expect(context.showsUserLocationMode == .showAndFollow)
|
||||
}
|
||||
|
||||
@Test
|
||||
func centerOnUserWithoutAuth() {
|
||||
context.showsUserLocationMode = .hide
|
||||
context.isLocationAuthorized = nil
|
||||
context.send(viewAction: .centerToUser)
|
||||
#expect(context.showsUserLocationMode == .showAndFollow)
|
||||
}
|
||||
|
||||
@Test
|
||||
func centerOnUserWithDeniedAuth() {
|
||||
context.isLocationAuthorized = false
|
||||
context.showsUserLocationMode = .hide
|
||||
context.send(viewAction: .centerToUser)
|
||||
#expect(context.showsUserLocationMode != .showAndFollow)
|
||||
#expect(context.alertInfo != nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
func errorMapping() {
|
||||
let mapError = AlertInfo(locationSharingViewError: .mapError(.failedLoadingMap))
|
||||
#expect(mapError.title == L10n.errorFailedLoadingMap(InfoPlistReader.main.bundleDisplayName))
|
||||
let locationError = AlertInfo(locationSharingViewError: .mapError(.failedLocatingUser))
|
||||
#expect(locationError.title == L10n.errorFailedLocatingUser(InfoPlistReader.main.bundleDisplayName))
|
||||
let authorizationError = AlertInfo(locationSharingViewError: .missingAuthorization)
|
||||
#expect(authorizationError.message == L10n.dialogPermissionLocationDescriptionIos(InfoPlistReader.main.bundleDisplayName))
|
||||
}
|
||||
|
||||
@Test
|
||||
func sendUserLocation() async throws {
|
||||
context.mapCenterLocation = .init(latitude: 0, longitude: 0)
|
||||
context.geolocationUncertainty = 10
|
||||
|
||||
let deferred = deferFulfillment(viewModel.actions) { $0 == .close }
|
||||
|
||||
try await confirmation { confirmation in
|
||||
timelineProxy.sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeClosure = { _, geoURI, _, _, assetType in
|
||||
#expect(geoURI.uncertainty == 10)
|
||||
#expect(assetType == .sender)
|
||||
confirmation()
|
||||
return .success(())
|
||||
}
|
||||
|
||||
context.send(viewAction: .selectLocation)
|
||||
|
||||
try await deferred.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
func sendPickedLocation() async throws {
|
||||
context.mapCenterLocation = .init(latitude: 0, longitude: 0)
|
||||
context.isLocationAuthorized = nil
|
||||
context.geolocationUncertainty = 10
|
||||
|
||||
let deferred = deferFulfillment(viewModel.actions) { $0 == .close }
|
||||
|
||||
try await confirmation { confirmation in
|
||||
timelineProxy.sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeClosure = { _, geoURI, _, _, assetType in
|
||||
#expect(geoURI.uncertainty == nil)
|
||||
#expect(assetType == .pin)
|
||||
confirmation()
|
||||
return .success(())
|
||||
}
|
||||
|
||||
context.send(viewAction: .selectLocation)
|
||||
|
||||
try await deferred.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user