// // Copyright 2021-2024 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 CoreLocation import SwiftUI typealias StaticLocationViewingViewModelType = StateStoreViewModel class StaticLocationViewingViewModel: StaticLocationViewingViewModelType, StaticLocationViewingViewModelProtocol { // MARK: - Properties // MARK: Private private var staticLocationSharingViewerService: StaticLocationSharingViewerServiceProtocol private var mapViewErrorAlertInfoBuilder: MapViewErrorAlertInfoBuilder // MARK: Public var completion: ((StaticLocationViewingViewModelResult) -> Void)? // MARK: - Setup init(mapStyleURL: URL, avatarData: AvatarInputProtocol, location: CLLocationCoordinate2D, coordinateType: LocationSharingCoordinateType, service: StaticLocationSharingViewerServiceProtocol) { staticLocationSharingViewerService = service let sharedAnnotation: LocationAnnotation switch coordinateType { case .user: sharedAnnotation = UserLocationAnnotation(avatarData: avatarData, coordinate: location) case .pin: sharedAnnotation = PinLocationAnnotation(coordinate: location) } let viewState = StaticLocationViewingViewState(mapStyleURL: mapStyleURL, userAvatarData: avatarData, sharedAnnotation: sharedAnnotation) mapViewErrorAlertInfoBuilder = MapViewErrorAlertInfoBuilder() super.init(initialViewState: viewState) state.errorSubject.sink { [weak self] error in guard let self = self else { return } self.processError(error) }.store(in: &cancellables) } // MARK: - Public override func process(viewAction: StaticLocationViewingViewAction) { switch viewAction { case .close: completion?(.close) case .share: completion?(.share(state.sharedAnnotation.coordinate)) case .mapCreditsDidTap: state.bindings.showMapCreditsSheet.toggle() case .showUserLocation: showsCurrentUserLocation() case .showMapCredit(mapAttribution: let mapAttribution): state.attribution = mapAttribution } } // MARK: - Private private func processError(_ error: LocationSharingViewError) { guard state.bindings.alertInfo == nil else { return } let alertInfo = mapViewErrorAlertInfoBuilder.build(with: error) { [weak self] in switch error { case .invalidLocationAuthorization: if let applicationSettingsURL = URL(string: UIApplication.openSettingsURLString) { UIApplication.shared.open(applicationSettingsURL) } else { self?.completion?(.close) } default: self?.completion?(.close) } } state.bindings.alertInfo = alertInfo } private func showsCurrentUserLocation() { if staticLocationSharingViewerService.requestAuthorizationIfNeeded() { state.showsUserLocationMode = .follow } else { state.errorSubject.send(.invalidLocationAuthorization) } } }