From 80103ebda28b711a408896ca9ca94be452b0b31e Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Mon, 25 Mar 2024 18:43:03 -0700 Subject: [PATCH] Revert user default updates, move everything to the map settings form --- Meshtastic/Extensions/UserDefaults.swift | 439 ++++++++++++++---- .../Map/MapContent/MeshMapContent.swift | 8 +- .../Nodes/Helpers/Map/MapSettingsForm.swift | 16 +- .../Nodes/Helpers/Map/NodeMapSwiftUI.swift | 6 +- Meshtastic/Views/Nodes/MeshMap.swift | 27 +- 5 files changed, 363 insertions(+), 133 deletions(-) diff --git a/Meshtastic/Extensions/UserDefaults.swift b/Meshtastic/Extensions/UserDefaults.swift index b497495d..ccb8a7a3 100644 --- a/Meshtastic/Extensions/UserDefaults.swift +++ b/Meshtastic/Extensions/UserDefaults.swift @@ -4,29 +4,15 @@ // // Copyright(c) Garth Vander Houwen 4/24/23. // +// +// UserDefaults.swift +// Meshtastic +// +// Copyright(c) Garth Vander Houwen 4/24/23. +// import Foundation -@propertyWrapper -struct UserDefault { - let key: UserDefaults.Keys - let defaultValue: T - - init(_ key: UserDefaults.Keys, defaultValue: T) { - self.key = key - self.defaultValue = defaultValue - } - - var wrappedValue: T { - get { - UserDefaults.standard.object(forKey: key.rawValue) as? T ?? defaultValue - } - set { - UserDefaults.standard.set(newValue, forKey: key.rawValue) - } - } -} - extension UserDefaults { enum Keys: String, CaseIterable { case preferredPeripheralId @@ -35,20 +21,15 @@ extension UserDefaults { case provideLocationInterval case mapLayer case meshMapDistance + case enableMapWaypoints case meshMapRecentering case meshMapShowNodeHistory case meshMapShowRouteLines case enableMapConvexHull - case enableMapRecentering - case enableMapNodeHistoryPins - case enableMapRouteLines case enableMapTraffic case enableMapPointsOfInterest case enableOfflineMaps - case enableOfflineMapsMBTiles case mapTileServer - case enableOverlayServer - case mapOverlayServer case mapTilesAboveLabels case mapUseLegacy case enableDetectionNotifications @@ -61,76 +42,340 @@ extension UserDefaults { func reset() { Keys.allCases.forEach { removeObject(forKey: $0.rawValue) } } - - @UserDefault(.preferredPeripheralId, defaultValue: "") - static var preferredPeripheralId: String - - @UserDefault(.preferredPeripheralNum, defaultValue: 0) - static var preferredPeripheralNum: Int - - @UserDefault(.provideLocation, defaultValue: false) - static var provideLocation: Bool - - @UserDefault(.provideLocationInterval, defaultValue: 0) - static var provideLocationInterval: Int - - @UserDefault(.mapLayer, defaultValue: .standard) - static var mapLayer: MapLayer - - @UserDefault(.meshMapDistance, defaultValue: 800000) - static var meshMapDistance: Double + static var preferredPeripheralId: String { + get { + UserDefaults.standard.string(forKey: "preferredPeripheralId") ?? "" + } + set { + UserDefaults.standard.set(newValue, forKey: "preferredPeripheralId") + } + } + static var preferredPeripheralNum: Int { + get { + UserDefaults.standard.integer(forKey: "preferredPeripheralNum") + } + set { + UserDefaults.standard.set(newValue, forKey: "preferredPeripheralNum") + } + } + static var provideLocation: Bool { + get { + UserDefaults.standard.bool(forKey: "provideLocation") + } set { + UserDefaults.standard.set(newValue, forKey: "provideLocation") + } + } + static var provideLocationInterval: Int { + get { + UserDefaults.standard.integer(forKey: "provideLocationInterval") + } + set { + UserDefaults.standard.set(newValue, forKey: "provideLocationInterval") + } + } + static var mapLayer: MapLayer { + get { + MapLayer(rawValue: UserDefaults.standard.string(forKey: "mapLayer") ?? MapLayer.standard.rawValue) ?? MapLayer.standard + } + set { + UserDefaults.standard.set(newValue.rawValue, forKey: "mapLayer") + } + } + static var meshMapDistance: Double { + get { + UserDefaults.standard.double(forKey: "meshMapDistance") + } + set { + UserDefaults.standard.set(newValue, forKey: "meshMapDistance") + } + } + static var enableMapWaypoints: Bool { + get { + UserDefaults.standard.bool(forKey: "enableMapWaypoints") + } + set { + UserDefaults.standard.set(newValue, forKey: "enableMapWaypoints") + } + } + static var enableMapRecentering: Bool { + get { + UserDefaults.standard.bool(forKey: "meshMapRecentering") + } + set { + UserDefaults.standard.set(newValue, forKey: "meshMapRecentering") + } + } + static var enableMapNodeHistoryPins: Bool { + get { + UserDefaults.standard.bool(forKey: "meshMapShowNodeHistory") + } + set { + UserDefaults.standard.set(newValue, forKey: "meshMapShowNodeHistory") + } + } + static var enableMapRouteLines: Bool { + get { + UserDefaults.standard.bool(forKey: "meshMapShowRouteLines") + } + set { + UserDefaults.standard.set(newValue, forKey: "meshMapShowRouteLines") + } + } + static var enableMapConvexHull: Bool { + get { + UserDefaults.standard.bool(forKey: "enableMapConvexHull") + } + set { + UserDefaults.standard.set(newValue, forKey: "enableMapConvexHull") + } + } + static var enableMapTraffic: Bool { + get { + UserDefaults.standard.bool(forKey: "enableMapTraffic") + } + set { + UserDefaults.standard.set(newValue, forKey: "enableMapTraffic") + } + } + static var enableMapPointsOfInterest: Bool { + get { + UserDefaults.standard.bool(forKey: "enableMapPointsOfInterest") + } + set { + UserDefaults.standard.set(newValue, forKey: "enableMapPointsOfInterest") + } + } + static var enableOfflineMaps: Bool { + get { + UserDefaults.standard.bool(forKey: "enableOfflineMaps") + } + set { + UserDefaults.standard.set(newValue, forKey: "enableOfflineMaps") + } + } + static var enableOfflineMapsMBTiles: Bool { + get { + UserDefaults.standard.bool(forKey: "enableOfflineMapsMBTiles") + } + set { + UserDefaults.standard.set(newValue, forKey: "enableOfflineMapsMBTiles") + } + } + static var mapTileServer: MapTileServer { + get { + MapTileServer(rawValue: UserDefaults.standard.string(forKey: "mapTileServer") ?? MapTileServer.openStreetMap.rawValue) ?? MapTileServer.openStreetMap + } + set { + UserDefaults.standard.set(newValue.rawValue, forKey: "mapTileServer") + } + } + static var enableOverlayServer: Bool { + get { + UserDefaults.standard.bool(forKey: "enableOverlayServer") + } + set { + UserDefaults.standard.set(newValue, forKey: "enableOverlayServer") + } + } + static var mapOverlayServer: MapOverlayServer { + get { + MapOverlayServer(rawValue: UserDefaults.standard.string(forKey: "mapOverlayServer") ?? MapOverlayServer.baseReReflectivityCurrent.rawValue) ?? MapOverlayServer.baseReReflectivityCurrent + } + set { + UserDefaults.standard.set(newValue.rawValue, forKey: "mapOverlayServer") + } + } + static var mapTilesAboveLabels: Bool { + get { + UserDefaults.standard.bool(forKey: "mapTilesAboveLabels") + } + set { + UserDefaults.standard.set(newValue, forKey: "mapTilesAboveLabels") + } + } - @UserDefault(.enableMapRecentering, defaultValue: false) - static var enableMapRecentering: Bool - - @UserDefault(.enableMapNodeHistoryPins, defaultValue: false) - static var enableMapNodeHistoryPins: Bool - - @UserDefault(.enableMapRouteLines, defaultValue: false) - static var enableMapRouteLines: Bool - - @UserDefault(.enableMapConvexHull, defaultValue: false) - static var enableMapConvexHull: Bool - - @UserDefault(.enableMapTraffic, defaultValue: false) - static var enableMapTraffic: Bool - - @UserDefault(.enableMapPointsOfInterest, defaultValue: false) - static var enableMapPointsOfInterest: Bool - - @UserDefault(.enableOfflineMaps, defaultValue: false) - static var enableOfflineMaps: Bool - - @UserDefault(.enableOfflineMapsMBTiles, defaultValue: false) - static var enableOfflineMapsMBTiles: Bool - - @UserDefault(.mapTileServer, defaultValue: .openStreetMap) - static var mapTileServer: MapTileServer - - @UserDefault(.enableOverlayServer, defaultValue: false) - static var enableOverlayServer: Bool - - @UserDefault(.mapOverlayServer, defaultValue: .baseReReflectivityCurrent) - static var mapOverlayServer: MapOverlayServer - - @UserDefault(.mapTilesAboveLabels, defaultValue: false) - static var mapTilesAboveLabels: Bool - - @UserDefault(.mapUseLegacy, defaultValue: false) - static var mapUseLegacy: Bool - - @UserDefault(.enableDetectionNotifications, defaultValue: false) - static var enableDetectionNotifications: Bool - - @UserDefault(.detectionSensorRole, defaultValue: .sensor) - static var detectionSensorRole: DetectionSensorRole - - @UserDefault(.enableSmartPosition, defaultValue: false) - static var enableSmartPosition: Bool - - @UserDefault(.modemPreset, defaultValue: 0) - static var modemPreset: Int - - @UserDefault(.firmwareVersion, defaultValue: "0.0.0") - static var firmwareVersion: String + static var mapUseLegacy: Bool { + get { + UserDefaults.standard.bool(forKey: "mapUseLegacy") + } + set { + UserDefaults.standard.set(newValue, forKey: "mapUseLegacy") + } + } + + static var enableDetectionNotifications: Bool { + get { + UserDefaults.standard.bool(forKey: "enableDetectionNotifications") + } + set { + UserDefaults.standard.set(newValue, forKey: "enableDetectionNotifications") + } + } + + static var detectionSensorRole: DetectionSensorRole { + get { + DetectionSensorRole(rawValue: UserDefaults.standard.string(forKey: "detectionSensorRole") ?? DetectionSensorRole.sensor.rawValue) ?? DetectionSensorRole.sensor + } + set { + UserDefaults.standard.set(newValue.rawValue, forKey: "detectionSensorRole") + } + } + static var enableSmartPosition: Bool { + get { + UserDefaults.standard.bool(forKey: "enableSmartPosition") + } + set { + UserDefaults.standard.set(newValue, forKey: "enableSmartPosition") + } + } + static var modemPreset: Int { + get { + UserDefaults.standard.integer(forKey: "modemPreset") + } + set { + UserDefaults.standard.set(newValue, forKey: "modemPreset") + } + } + static var firmwareVersion: String { + get { + UserDefaults.standard.string(forKey: "firmwareVersion") ?? "0.0.0" + } + set { + UserDefaults.standard.set(newValue, forKey: "firmwareVersion") + } + } } + +//import Foundation +// +//@propertyWrapper +//struct UserDefault { +// let key: UserDefaults.Keys +// let defaultValue: T +// +// init(_ key: UserDefaults.Keys, defaultValue: T) { +// self.key = key +// self.defaultValue = defaultValue +// } +// +// var wrappedValue: T { +// get { +// UserDefaults.standard.object(forKey: key.rawValue) as? T ?? defaultValue +// } +// set { +// UserDefaults.standard.set(newValue, forKey: key.rawValue) +// } +// } +//} +// +//extension UserDefaults { +// enum Keys: String, CaseIterable { +// case preferredPeripheralId +// case preferredPeripheralNum +// case provideLocation +// case provideLocationInterval +// case mapLayer +// case meshMapDistance +// case enableMapWaypoints +// case meshMapRecentering +// case meshMapShowNodeHistory +// case meshMapShowRouteLines +// case enableMapConvexHull +// case enableMapRecentering +// case enableMapNodeHistoryPins +// case enableMapRouteLines +// case enableMapTraffic +// case enableMapPointsOfInterest +// case enableOfflineMaps +// case enableOfflineMapsMBTiles +// case mapTileServer +// case enableOverlayServer +// case mapOverlayServer +// case mapTilesAboveLabels +// case mapUseLegacy +// case enableDetectionNotifications +// case detectionSensorRole +// case enableSmartPosition +// case modemPreset +// case firmwareVersion +// } +// +// func reset() { +// Keys.allCases.forEach { removeObject(forKey: $0.rawValue) } +// } +// +// @UserDefault(.preferredPeripheralId, defaultValue: "") +// static var preferredPeripheralId: String +// +// @UserDefault(.preferredPeripheralNum, defaultValue: 0) +// static var preferredPeripheralNum: Int +// +// @UserDefault(.provideLocation, defaultValue: false) +// static var provideLocation: Bool +// +// @UserDefault(.provideLocationInterval, defaultValue: 0) +// static var provideLocationInterval: Int +// +// @UserDefault(.mapLayer, defaultValue: .standard) +// static var mapLayer: MapLayer +// +// @UserDefault(.meshMapDistance, defaultValue: 800000) +// static var meshMapDistance: Double +// +// @UserDefault(.enableMapWaypoints, defaultValue: false) +// static var enableMapWaypoints: Bool +// +// @UserDefault(.enableMapRecentering, defaultValue: false) +// static var enableMapRecentering: Bool +// +// @UserDefault(.enableMapNodeHistoryPins, defaultValue: false) +// static var enableMapNodeHistoryPins: Bool +// +// @UserDefault(.enableMapRouteLines, defaultValue: false) +// static var enableMapRouteLines: Bool +// +// @UserDefault(.enableMapConvexHull, defaultValue: false) +// static var enableMapConvexHull: Bool +// +// @UserDefault(.enableMapTraffic, defaultValue: false) +// static var enableMapTraffic: Bool +// +// @UserDefault(.enableMapPointsOfInterest, defaultValue: false) +// static var enableMapPointsOfInterest: Bool +// +// @UserDefault(.enableOfflineMaps, defaultValue: false) +// static var enableOfflineMaps: Bool +// +// @UserDefault(.enableOfflineMapsMBTiles, defaultValue: false) +// static var enableOfflineMapsMBTiles: Bool +// +// @UserDefault(.mapTileServer, defaultValue: .openStreetMap) +// static var mapTileServer: MapTileServer +// +// @UserDefault(.enableOverlayServer, defaultValue: false) +// static var enableOverlayServer: Bool +// +// @UserDefault(.mapOverlayServer, defaultValue: .baseReReflectivityCurrent) +// static var mapOverlayServer: MapOverlayServer +// +// @UserDefault(.mapTilesAboveLabels, defaultValue: false) +// static var mapTilesAboveLabels: Bool +// +// @UserDefault(.mapUseLegacy, defaultValue: false) +// static var mapUseLegacy: Bool +// +// @UserDefault(.enableDetectionNotifications, defaultValue: false) +// static var enableDetectionNotifications: Bool +// +// @UserDefault(.detectionSensorRole, defaultValue: .sensor) +// static var detectionSensorRole: DetectionSensorRole +// +// @UserDefault(.enableSmartPosition, defaultValue: false) +// static var enableSmartPosition: Bool +// +// @UserDefault(.modemPreset, defaultValue: 0) +// static var modemPreset: Int +// +// @UserDefault(.firmwareVersion, defaultValue: "0.0.0") +// static var firmwareVersion: String +//} diff --git a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift index 7a96c3d1..e64febb5 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift @@ -18,15 +18,15 @@ struct MeshMapContent: MapContent { @State var routes: [RouteEntity] = [] /// Parameters @Binding var showUserLocation: Bool - @Binding var showNodeHistory: Bool - @Binding var showRouteLines: Bool - @Binding var showConvexHull: Bool + @AppStorage("meshMapShowNodeHistory") private var showNodeHistory = false + @AppStorage("meshMapShowRouteLines") private var showRouteLines = false + @AppStorage("enableMapConvexHull") private var showConvexHull = false @Binding var showTraffic: Bool @Binding var showPointsOfInterest: Bool @Binding var selectedMapLayer: MapLayer // Map Configuration @Binding var selectedPosition: PositionEntity? - @Binding var showWaypoints: Bool + @AppStorage("enableMapWaypoints") private var showWaypoints = false @Binding var selectedWaypoint: WaypointEntity? @FetchRequest(fetchRequest: PositionEntity.allPositionsFetchRequest(), animation: .easeIn) diff --git a/Meshtastic/Views/Nodes/Helpers/Map/MapSettingsForm.swift b/Meshtastic/Views/Nodes/Helpers/Map/MapSettingsForm.swift index 6a65c356..80d6a61f 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/MapSettingsForm.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/MapSettingsForm.swift @@ -13,13 +13,14 @@ import MapKit @available(iOS 17.0, macOS 14.0, *) struct MapSettingsForm: View { @Environment(\.dismiss) private var dismiss - @Binding var nodeHistory: Bool - @Binding var routeLines: Bool - @Binding var convexHull: Bool + @AppStorage("meshMapShowNodeHistory") private var nodeHistory = false + @AppStorage("meshMapShowRouteLines") private var routeLines = false + @AppStorage("enableMapConvexHull") private var convexHull = false + @AppStorage("enableMapWaypoints") private var waypoints = false @Binding var traffic: Bool @Binding var pointsOfInterest: Bool @Binding var mapLayer: MapLayer - @Binding var meshMapDistance: Double + @AppStorage("meshMapDistance") private var meshMapDistance: Double = 800000 @Binding var meshMap: Bool var body: some View { @@ -55,6 +56,13 @@ struct MapSettingsForm: View { UserDefaults.meshMapDistance = newMeshMapDistance } } + Toggle(isOn: $waypoints) { + Label("Show Waypoints ", systemImage: "signpost.right.and.left") + } + .toggleStyle(SwitchToggleStyle(tint: .accentColor)) + .onTapGesture { + UserDefaults.enableMapWaypoints = !waypoints + } Toggle(isOn: $nodeHistory) { Label("Node History", systemImage: "building.columns.fill") } diff --git a/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift b/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift index 282a5a8c..bd512e94 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift @@ -20,10 +20,6 @@ struct NodeMapSwiftUI: View { @State var showUserLocation: Bool = false @State var positions: [PositionEntity] = [] /// Map State User Defaults - @AppStorage("meshMapDistance") private var meshMapDistance: Double = 800000 - @AppStorage("meshMapShowNodeHistory") private var showNodeHistory = false - @AppStorage("meshMapShowRouteLines") private var showRouteLines = false - @AppStorage("enableMapConvexHull") private var showConvexHull = false @AppStorage("enableMapTraffic") private var showTraffic: Bool = false @AppStorage("enableMapPointsOfInterest") private var showPointsOfInterest: Bool = false @AppStorage("mapLayer") private var selectedMapLayer: MapLayer = .hybrid @@ -87,7 +83,7 @@ struct NodeMapSwiftUI: View { } } .sheet(isPresented: $isEditingSettings) { - MapSettingsForm(nodeHistory: $showNodeHistory, routeLines: $showRouteLines, convexHull: $showConvexHull, traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMapDistance: $meshMapDistance, meshMap: $isMeshMap) + MapSettingsForm(traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMap: $isMeshMap) .onChange(of: (selectedMapLayer)) { newMapLayer in switch selectedMapLayer { case .standard: diff --git a/Meshtastic/Views/Nodes/MeshMap.swift b/Meshtastic/Views/Nodes/MeshMap.swift index 8dee5f86..0787ea55 100644 --- a/Meshtastic/Views/Nodes/MeshMap.swift +++ b/Meshtastic/Views/Nodes/MeshMap.swift @@ -24,10 +24,6 @@ struct MeshMap: View { /// Parameters @State var showUserLocation: Bool = true /// Map State User Defaults - @AppStorage("meshMapDistance") private var meshMapDistance: Double = 800000 - @AppStorage("meshMapShowNodeHistory") private var showNodeHistory = false - @AppStorage("meshMapShowRouteLines") private var showRouteLines = false - @AppStorage("enableMapConvexHull") private var showConvexHull = false @AppStorage("enableMapTraffic") private var showTraffic: Bool = false @AppStorage("enableMapPointsOfInterest") private var showPointsOfInterest: Bool = false @AppStorage("mapLayer") private var selectedMapLayer: MapLayer = .standard @@ -37,7 +33,6 @@ struct MeshMap: View { @State var position = MapCameraPosition.automatic @State var isEditingSettings = false @State var selectedPosition: PositionEntity? - @State var showWaypoints = false @State var editingWaypoint: WaypointEntity? @State var selectedWaypoint: WaypointEntity? @State var newWaypointCoord: CLLocationCoordinate2D? @@ -54,7 +49,7 @@ struct MeshMap: View { ZStack { MapReader { reader in Map(position: $position, bounds: MapCameraBounds(minimumDistance: 1, maximumDistance: .infinity), scope: mapScope) { - MeshMapContent(routes: Array(routes), showUserLocation: $showUserLocation, showNodeHistory: $showNodeHistory, showRouteLines: $showRouteLines, showConvexHull: $showConvexHull, showTraffic: $showTraffic, showPointsOfInterest: $showPointsOfInterest, selectedMapLayer: $selectedMapLayer, selectedPosition: $selectedPosition, showWaypoints: $showWaypoints, selectedWaypoint: $selectedWaypoint) + MeshMapContent(routes: Array(routes), showUserLocation: $showUserLocation, showTraffic: $showTraffic, showPointsOfInterest: $showPointsOfInterest, selectedMapLayer: $selectedMapLayer, selectedPosition: $selectedPosition, selectedWaypoint: $selectedWaypoint) } .mapScope(mapScope) @@ -116,7 +111,7 @@ struct MeshMap: View { .padding() } .sheet(isPresented: $isEditingSettings) { - MapSettingsForm(nodeHistory: $showNodeHistory, routeLines: $showRouteLines, convexHull: $showConvexHull, traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMapDistance: $meshMapDistance, meshMap: $isMeshMap) + MapSettingsForm(traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMap: $isMeshMap) } .onChange(of: (appState.navigationPath)) { newPath in @@ -141,7 +136,7 @@ struct MeshMap: View { // print("Waypoint not found") // return // } - showWaypoints = true + //showWaypoints = true //position = .camera(MapCamera(centerCoordinate: waypoint.coordinate, distance: 1000, heading: 0, pitch: 60)) } } @@ -172,21 +167,7 @@ struct MeshMap: View { } .tint(Color(UIColor.secondarySystemBackground)) .foregroundColor(.accentColor) - .buttonStyle(.borderedProminent) - /// Show / Hide Waypoints Button - - Button(action: { - withAnimation { - showWaypoints = !showWaypoints - } - }) { - Image(systemName: showWaypoints ? "signpost.right.and.left.fill" : "signpost.right.and.left") - .padding(.vertical, 5) - } - .tint(Color(UIColor.secondarySystemBackground)) - .foregroundColor(.accentColor) - .buttonStyle(.borderedProminent) - + .buttonStyle(.borderedProminent) } .controlSize(.regular) .padding(5)