mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
allow users to set live location minimum distance update
This commit is contained in:
@@ -66,6 +66,7 @@ final class AppSettings {
|
|||||||
|
|
||||||
case voiceMessagePlaybackSpeed
|
case voiceMessagePlaybackSpeed
|
||||||
case liveLocationSharingTimeoutDatesByRoomID
|
case liveLocationSharingTimeoutDatesByRoomID
|
||||||
|
case liveLocationMinimumDistanceUpdate
|
||||||
|
|
||||||
// Feature flags
|
// Feature flags
|
||||||
case publicSearchEnabled
|
case publicSearchEnabled
|
||||||
@@ -349,6 +350,9 @@ final class AppSettings {
|
|||||||
@UserPreference(key: UserDefaultsKeys.liveLocationSharingTimeoutDatesByRoomID, defaultValue: [String: Date](), storageType: .userDefaults(store))
|
@UserPreference(key: UserDefaultsKeys.liveLocationSharingTimeoutDatesByRoomID, defaultValue: [String: Date](), storageType: .userDefaults(store))
|
||||||
var liveLocationSharingTimeoutDatesByRoomID
|
var liveLocationSharingTimeoutDatesByRoomID
|
||||||
|
|
||||||
|
@UserPreference(key: UserDefaultsKeys.liveLocationMinimumDistanceUpdate, defaultValue: 10, storageType: .userDefaults(store))
|
||||||
|
var liveLocationMinimumDistanceUpdate
|
||||||
|
|
||||||
@UserPreference(key: UserDefaultsKeys.frequentlyUsedSystemEmojis, defaultValue: [FrequentlyUsedEmoji](), storageType: .userDefaults(store))
|
@UserPreference(key: UserDefaultsKeys.frequentlyUsedSystemEmojis, defaultValue: [FrequentlyUsedEmoji](), storageType: .userDefaults(store))
|
||||||
var frequentlyUsedSystemEmojis
|
var frequentlyUsedSystemEmojis
|
||||||
|
|
||||||
|
|||||||
@@ -2199,6 +2199,11 @@ class CLLocationManagerMock: CLLocationManagerProtocol, @unchecked Sendable {
|
|||||||
set(value) { underlyingDesiredAccuracy = value }
|
set(value) { underlyingDesiredAccuracy = value }
|
||||||
}
|
}
|
||||||
var underlyingDesiredAccuracy: CLLocationAccuracy!
|
var underlyingDesiredAccuracy: CLLocationAccuracy!
|
||||||
|
var distanceFilter: CLLocationDistance {
|
||||||
|
get { return underlyingDistanceFilter }
|
||||||
|
set(value) { underlyingDistanceFilter = value }
|
||||||
|
}
|
||||||
|
var underlyingDistanceFilter: CLLocationDistance!
|
||||||
var pausesLocationUpdatesAutomatically: Bool {
|
var pausesLocationUpdatesAutomatically: Bool {
|
||||||
get { return underlyingPausesLocationUpdatesAutomatically }
|
get { return underlyingPausesLocationUpdatesAutomatically }
|
||||||
set(value) { underlyingPausesLocationUpdatesAutomatically = value }
|
set(value) { underlyingPausesLocationUpdatesAutomatically = value }
|
||||||
|
|||||||
+21
-2
@@ -7,12 +7,30 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
struct AdvancedSettingsScreenViewState: BindableState {
|
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 timelineMediaVisibility: TimelineMediaVisibility
|
||||||
var hideInviteAvatars: Bool
|
var hideInviteAvatars: Bool
|
||||||
var isWaitingTimelineMediaVisibility = false
|
var isWaitingTimelineMediaVisibility: Bool
|
||||||
var isWaitingHideInviteAvatars = false
|
var isWaitingHideInviteAvatars: Bool
|
||||||
var bindings: AdvancedSettingsScreenViewStateBindings
|
var bindings: AdvancedSettingsScreenViewStateBindings
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +60,7 @@ protocol AdvancedSettingsProtocol: AnyObject {
|
|||||||
var appAppearance: AppAppearance { get set }
|
var appAppearance: AppAppearance { get set }
|
||||||
var sharePresence: Bool { get set }
|
var sharePresence: Bool { get set }
|
||||||
var optimizeMediaUploads: Bool { get set }
|
var optimizeMediaUploads: Bool { get set }
|
||||||
|
var liveLocationMinimumDistanceUpdate: Int { get set }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AppSettings: AdvancedSettingsProtocol { }
|
extension AppSettings: AdvancedSettingsProtocol { }
|
||||||
|
|||||||
+25
@@ -37,6 +37,7 @@ struct AdvancedSettingsScreen: View {
|
|||||||
|
|
||||||
moderationAndSafetySection
|
moderationAndSafetySection
|
||||||
timelineMediaSection
|
timelineMediaSection
|
||||||
|
liveLocationSection
|
||||||
}
|
}
|
||||||
.compoundList()
|
.compoundList()
|
||||||
.navigationTitle(L10n.commonAdvancedSettings)
|
.navigationTitle(L10n.commonAdvancedSettings)
|
||||||
@@ -84,6 +85,30 @@ struct AdvancedSettingsScreen: View {
|
|||||||
.compoundListSectionFooter()
|
.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 {
|
private extension AppAppearance {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ protocol CLLocationManagerProtocol: AnyObject {
|
|||||||
var delegate: CLLocationManagerDelegate? { get set }
|
var delegate: CLLocationManagerDelegate? { get set }
|
||||||
var allowsBackgroundLocationUpdates: Bool { get set }
|
var allowsBackgroundLocationUpdates: Bool { get set }
|
||||||
var desiredAccuracy: CLLocationAccuracy { get set }
|
var desiredAccuracy: CLLocationAccuracy { get set }
|
||||||
|
var distanceFilter: CLLocationDistance { get set }
|
||||||
var pausesLocationUpdatesAutomatically: Bool { get set }
|
var pausesLocationUpdatesAutomatically: Bool { get set }
|
||||||
var authorizationStatus: CLAuthorizationStatus { get }
|
var authorizationStatus: CLAuthorizationStatus { get }
|
||||||
|
|
||||||
|
|||||||
@@ -47,9 +47,8 @@ class LiveLocationManager: NSObject, LiveLocationManagerProtocol, CLLocationMana
|
|||||||
|
|
||||||
self.locationManager.delegate = self
|
self.locationManager.delegate = self
|
||||||
self.locationManager.allowsBackgroundLocationUpdates = true
|
self.locationManager.allowsBackgroundLocationUpdates = true
|
||||||
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
|
|
||||||
self.locationManager.pausesLocationUpdatesAutomatically = false
|
self.locationManager.pausesLocationUpdatesAutomatically = false
|
||||||
|
setupMinumDistance(appSettings.liveLocationMinimumDistanceUpdate)
|
||||||
setupSubscriptions()
|
setupSubscriptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,6 +161,27 @@ class LiveLocationManager: NSObject, LiveLocationManagerProtocol, CLLocationMana
|
|||||||
locationUpdatesTask = nil
|
locationUpdatesTask = nil
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.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]) {
|
private func syncActiveRoomProxies(with sessions: [String: Date]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user