178 lines
6.3 KiB
Swift
178 lines
6.3 KiB
Swift
//
|
|
// Copyright 2022-2024 New Vector Ltd.
|
|
//
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
// Please see LICENSE in the repository root for full details.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// UserLocationServiceProvider enables to automatically store UserLocationService per user id and retrieve existing UserLocationService.
|
|
/// Note: UserLocationService management is not set inside UserSessionsService at the moment to avoid to expose user location management to extension targets.
|
|
class UserLocationServiceProvider {
|
|
|
|
// MARK: - Constants
|
|
|
|
static let shared = UserLocationServiceProvider()
|
|
|
|
// MARK: - Properties
|
|
|
|
// UserLocationService per user id
|
|
private var locationServices: [String: UserLocationServiceProtocol] = [:]
|
|
|
|
// MARK: - Setup
|
|
|
|
private init() {
|
|
self.setupOrTeardownLocationServices()
|
|
|
|
// Listen to lab flag changes
|
|
self.registerRiotSettingsNotifications()
|
|
}
|
|
|
|
// MARK: - Public
|
|
|
|
func locationService(for userId: String) -> UserLocationServiceProtocol? {
|
|
return self.locationServices[userId]
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
// MARK: Store
|
|
|
|
private func addLocationService(_ userLocationService: UserLocationServiceProtocol, for userId: String) {
|
|
self.locationServices[userId] = userLocationService
|
|
}
|
|
|
|
private func removeLocationService(for userId: String) {
|
|
self.locationServices[userId] = nil
|
|
}
|
|
|
|
// MARK: UserLocationService setup
|
|
|
|
private func setupUserLocationService(for userSession: UserSession) {
|
|
|
|
self.tearDownUserLocationService(for: userSession.userId)
|
|
|
|
let userLocationService = UserLocationService(session: userSession.matrixSession)
|
|
|
|
self.addLocationService(userLocationService, for: userSession.userId)
|
|
|
|
userLocationService.start()
|
|
|
|
MXLog.debug("Start monitoring user live location sharing")
|
|
}
|
|
|
|
private func setupUserLocationServiceIfNeeded(for userSession: UserSession) {
|
|
|
|
// Be sure Matrix session has is store setup to access beacon info summaries
|
|
guard userSession.matrixSession.state.rawValue >= MXSessionState.storeDataReady.rawValue else {
|
|
return
|
|
}
|
|
|
|
let locationService = self.locationService(for: userSession.userId)
|
|
|
|
guard locationService == nil else {
|
|
return
|
|
}
|
|
|
|
self.setupUserLocationService(for: userSession)
|
|
}
|
|
|
|
private func tearDownUserLocationService(for userId: String) {
|
|
|
|
guard let locationService = self.locationService(for: userId) else {
|
|
return
|
|
}
|
|
|
|
locationService.stop()
|
|
|
|
self.removeLocationService(for: userId)
|
|
|
|
MXLog.debug("Stop monitoring user live location sharing")
|
|
}
|
|
|
|
private func setupOrTeardownLocationServices() {
|
|
|
|
self.unregisterUserSessionsServiceNotifications()
|
|
|
|
if RiotSettings.shared.enableLiveLocationSharing {
|
|
self.setupUserLocationServiceForAllUsers()
|
|
self.registerUserSessionsServiceNotifications()
|
|
} else {
|
|
self.tearDownUserLocationServiceForAllUsers()
|
|
}
|
|
}
|
|
|
|
private func setupUserLocationServiceForAllUsers() {
|
|
for userSession in UserSessionsService.shared.userSessions {
|
|
self.setupUserLocationService(for: userSession)
|
|
}
|
|
}
|
|
|
|
private func tearDownUserLocationServiceForAllUsers() {
|
|
for (userId, _) in self.locationServices {
|
|
self.tearDownUserLocationService(for: userId)
|
|
}
|
|
}
|
|
|
|
// MARK: UserSessions management
|
|
|
|
private func registerUserSessionsServiceNotifications() {
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(userSessionsServiceDidAddUserSession(_:)), name: UserSessionsService.didAddUserSession, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(userSessionsServiceDidUpdateUserSession(_:)), name: UserSessionsService.userSessionDidChange, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(userSessionsServiceDidRemoveUserSession(_:)), name: UserSessionsService.didRemoveUserSession, object: nil)
|
|
}
|
|
|
|
private func unregisterUserSessionsServiceNotifications() {
|
|
|
|
NotificationCenter.default.removeObserver(self, name: UserSessionsService.didAddUserSession, object: nil)
|
|
|
|
NotificationCenter.default.removeObserver(self, name: UserSessionsService.userSessionDidChange, object: nil)
|
|
|
|
NotificationCenter.default.removeObserver(self, name: UserSessionsService.didRemoveUserSession, object: nil)
|
|
}
|
|
|
|
@objc private func userSessionsServiceDidAddUserSession(_ notification: Notification) {
|
|
|
|
guard let userInfo = notification.userInfo, let userSession = userInfo[UserSessionsService.NotificationUserInfoKey.userSession] as? UserSession else {
|
|
return
|
|
}
|
|
|
|
self.setupUserLocationServiceIfNeeded(for: userSession)
|
|
}
|
|
|
|
@objc private func userSessionsServiceDidUpdateUserSession(_ notification: Notification) {
|
|
|
|
guard let userInfo = notification.userInfo, let userSession = userInfo[UserSessionsService.NotificationUserInfoKey.userSession] as? UserSession else {
|
|
return
|
|
}
|
|
|
|
self.setupUserLocationServiceIfNeeded(for: userSession)
|
|
}
|
|
|
|
@objc private func userSessionsServiceDidRemoveUserSession(_ notification: Notification) {
|
|
|
|
guard let userInfo = notification.userInfo, let userId = userInfo[UserSessionsService.NotificationUserInfoKey.userId] as? String else {
|
|
return
|
|
}
|
|
|
|
self.tearDownUserLocationService(for: userId)
|
|
}
|
|
|
|
// MARK: - RiotSettings
|
|
|
|
private func registerRiotSettingsNotifications() {
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(riotSettingsDidUpdateLiveLocationSharingActivation(_:)), name: RiotSettings.didUpdateLiveLocationSharingActivation, object: nil)
|
|
}
|
|
|
|
@objc private func riotSettingsDidUpdateLiveLocationSharingActivation(_ notification: Notification) {
|
|
|
|
// Lab flag value has changed, check if we should enable or disable location services
|
|
self.setupOrTeardownLocationServices()
|
|
}
|
|
}
|