allow users to set live location minimum distance update

This commit is contained in:
Mauro Romito
2026-04-20 20:26:11 +02:00
committed by Mauro
parent f2d3945ff3
commit 693a76ecf0
6 changed files with 78 additions and 4 deletions

View File

@@ -66,6 +66,7 @@ final class AppSettings {
case voiceMessagePlaybackSpeed
case liveLocationSharingTimeoutDatesByRoomID
case liveLocationMinimumDistanceUpdate
// Feature flags
case publicSearchEnabled
@@ -349,6 +350,9 @@ final class AppSettings {
@UserPreference(key: UserDefaultsKeys.liveLocationSharingTimeoutDatesByRoomID, defaultValue: [String: Date](), storageType: .userDefaults(store))
var liveLocationSharingTimeoutDatesByRoomID
@UserPreference(key: UserDefaultsKeys.liveLocationMinimumDistanceUpdate, defaultValue: 10, storageType: .userDefaults(store))
var liveLocationMinimumDistanceUpdate
@UserPreference(key: UserDefaultsKeys.frequentlyUsedSystemEmojis, defaultValue: [FrequentlyUsedEmoji](), storageType: .userDefaults(store))
var frequentlyUsedSystemEmojis

View File

@@ -2199,6 +2199,11 @@ class CLLocationManagerMock: CLLocationManagerProtocol, @unchecked Sendable {
set(value) { underlyingDesiredAccuracy = value }
}
var underlyingDesiredAccuracy: CLLocationAccuracy!
var distanceFilter: CLLocationDistance {
get { return underlyingDistanceFilter }
set(value) { underlyingDistanceFilter = value }
}
var underlyingDistanceFilter: CLLocationDistance!
var pausesLocationUpdatesAutomatically: Bool {
get { return underlyingPausesLocationUpdatesAutomatically }
set(value) { underlyingPausesLocationUpdatesAutomatically = value }

View File

@@ -7,12 +7,30 @@
//
import Foundation
import UIKit
struct AdvancedSettingsScreenViewState: BindableState {
init(timelineMediaVisibility: TimelineMediaVisibility, hideInviteAvatars: Bool, isWaitingTimelineMediaVisibility: Bool = false, isWaitingHideInviteAvatars: Bool = false, bindings: AdvancedSettingsScreenViewStateBindings) {
self.timelineMediaVisibility = timelineMediaVisibility
self.hideInviteAvatars = hideInviteAvatars
self.isWaitingTimelineMediaVisibility = isWaitingTimelineMediaVisibility
self.isWaitingHideInviteAvatars = isWaitingHideInviteAvatars
self.bindings = bindings
let linkPlaceholder = "{link}"
var footerString = AttributedString(L10n.screenAdvancedSettingsLiveLocationSectionFooter(linkPlaceholder))
var linkString = AttributedString(L10n.screenAdvancedSettingsLiveLocationSectionFooterLink)
linkString.link = URL(string: UIApplication.openSettingsURLString)
linkString.bold()
footerString.replace(linkPlaceholder, with: linkString)
liveLocationUpdateFooterAttributedString = footerString
}
let liveLocationUpdateFooterAttributedString: AttributedString
var timelineMediaVisibility: TimelineMediaVisibility
var hideInviteAvatars: Bool
var isWaitingTimelineMediaVisibility = false
var isWaitingHideInviteAvatars = false
var isWaitingTimelineMediaVisibility: Bool
var isWaitingHideInviteAvatars: Bool
var bindings: AdvancedSettingsScreenViewStateBindings
}
@@ -42,6 +60,7 @@ protocol AdvancedSettingsProtocol: AnyObject {
var appAppearance: AppAppearance { get set }
var sharePresence: Bool { get set }
var optimizeMediaUploads: Bool { get set }
var liveLocationMinimumDistanceUpdate: Int { get set }
}
extension AppSettings: AdvancedSettingsProtocol { }

View File

@@ -37,6 +37,7 @@ struct AdvancedSettingsScreen: View {
moderationAndSafetySection
timelineMediaSection
liveLocationSection
}
.compoundList()
.navigationTitle(L10n.commonAdvancedSettings)
@@ -84,6 +85,30 @@ struct AdvancedSettingsScreen: View {
.compoundListSectionFooter()
}
}
private var liveLocationSection: some View {
Section {
ListRow(kind: .custom {
Stepper(L10n.screenAdvancedSettingsLiveLocationUpdateDistance(context.liveLocationMinimumDistanceUpdate),
value: $context.liveLocationMinimumDistanceUpdate, in: 1...100)
.font(.compound.bodyLG)
.foregroundStyle(.compound.textPrimary)
.padding(.horizontal, ListRowPadding.horizontal)
.padding(.vertical, ListRowPadding.vertical)
})
} header: {
VStack(alignment: .leading, spacing: 4) {
Text(L10n.screenAdvancedSettingsLiveLocationSectionTitle)
.compoundListSectionHeader()
Text(L10n.screenAdvancedSettingsLiveLocationSectionDescription)
.font(.compound.bodyMD)
.foregroundStyle(.compound.textSecondary)
}
} footer: {
Text(context.viewState.liveLocationUpdateFooterAttributedString)
.compoundListSectionFooter()
}
}
}
private extension AppAppearance {

View File

@@ -12,6 +12,7 @@ protocol CLLocationManagerProtocol: AnyObject {
var delegate: CLLocationManagerDelegate? { get set }
var allowsBackgroundLocationUpdates: Bool { get set }
var desiredAccuracy: CLLocationAccuracy { get set }
var distanceFilter: CLLocationDistance { get set }
var pausesLocationUpdatesAutomatically: Bool { get set }
var authorizationStatus: CLAuthorizationStatus { get }

View File

@@ -47,9 +47,8 @@ class LiveLocationManager: NSObject, LiveLocationManagerProtocol, CLLocationMana
self.locationManager.delegate = self
self.locationManager.allowsBackgroundLocationUpdates = true
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
self.locationManager.pausesLocationUpdatesAutomatically = false
setupMinumDistance(appSettings.liveLocationMinimumDistanceUpdate)
setupSubscriptions()
}
@@ -162,6 +161,27 @@ class LiveLocationManager: NSObject, LiveLocationManagerProtocol, CLLocationMana
locationUpdatesTask = nil
}
.store(in: &cancellables)
appSettings.$liveLocationMinimumDistanceUpdate
.removeDuplicates()
.debounce(for: .seconds(3), scheduler: DispatchQueue.main)
.sink { [weak self] minimumDistance in
self?.setupMinumDistance(minimumDistance)
}
.store(in: &cancellables)
}
/// Sets up the distance filter and the most optimal accuracy given the minimum distance to save battery,
private func setupMinumDistance(_ minimumDistance: Int) {
switch minimumDistance {
case 0..<10:
locationManager.desiredAccuracy = kCLLocationAccuracyBest
case 10..<100:
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
default:
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
}
locationManager.distanceFilter = CLLocationDistance(minimumDistance)
}
private func syncActiveRoomProxies(with sessions: [String: Date]) {