From 70e1bdb8352e4d2c862c71a0d3813eb2dbf9b9bc Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Thu, 9 Nov 2023 17:43:38 -0800 Subject: [PATCH] More map cleanup --- Meshtastic.xcodeproj/project.pbxproj | 16 +- .../Custom/LocalMBTileOverlay.swift | 0 .../Custom/MapButtons.swift | 0 .../Custom/MapViewFitExtension.swift | 0 .../Custom/MapViewSwiftUI.swift | 0 .../Map => MapKitMap}/NodeMapMapkit.swift | 2 +- .../WaypointFormMapKit.swift} | 2 +- .../Nodes/Helpers/Map/NodeMapSwiftUI.swift | 98 ++--------- .../Views/Nodes/Helpers/MapSettingsForm.swift | 38 +++-- .../Views/Nodes/Helpers/PositionPopover.swift | 18 +- Meshtastic/Views/Nodes/MeshMap.swift | 158 ++++++++++++++++-- Meshtastic/Views/Nodes/NodeMap.swift | 2 +- Meshtastic/Views/Settings/UserConfig.swift | 2 +- 13 files changed, 210 insertions(+), 126 deletions(-) rename Meshtastic/Views/{Map => MapKitMap}/Custom/LocalMBTileOverlay.swift (100%) rename Meshtastic/Views/{Map => MapKitMap}/Custom/MapButtons.swift (100%) rename Meshtastic/Views/{Map => MapKitMap}/Custom/MapViewFitExtension.swift (100%) rename Meshtastic/Views/{Map => MapKitMap}/Custom/MapViewSwiftUI.swift (100%) rename Meshtastic/Views/{Nodes/Helpers/Map => MapKitMap}/NodeMapMapkit.swift (99%) rename Meshtastic/Views/{Map/WaypointFormView.swift => MapKitMap/WaypointFormMapKit.swift} (99%) diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index aae9aff7..d9de399f 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -88,7 +88,7 @@ DD913639270DFF4C00D7ACF3 /* LocalNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */; }; DD94B7402ACCE3BE00DCD1D1 /* MapSettingsForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD94B73F2ACCE3BE00DCD1D1 /* MapSettingsForm.swift */; }; DD964FBD296E6B01007C176F /* EmojiOnlyTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FBC296E6B01007C176F /* EmojiOnlyTextField.swift */; }; - DD964FBF296E76EF007C176F /* WaypointFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FBE296E76EF007C176F /* WaypointFormView.swift */; }; + DD964FBF296E76EF007C176F /* WaypointFormMapKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FBE296E76EF007C176F /* WaypointFormMapKit.swift */; }; DD964FC2297272AE007C176F /* WaypointEntityExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FC1297272AE007C176F /* WaypointEntityExtension.swift */; }; DD964FC42974767D007C176F /* MapViewFitExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FC32974767D007C176F /* MapViewFitExtension.swift */; }; DD964FC62975DBFD007C176F /* QueryCoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD964FC52975DBFD007C176F /* QueryCoreData.swift */; }; @@ -299,7 +299,7 @@ DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalNotificationManager.swift; sourceTree = ""; }; DD94B73F2ACCE3BE00DCD1D1 /* MapSettingsForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapSettingsForm.swift; sourceTree = ""; }; DD964FBC296E6B01007C176F /* EmojiOnlyTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiOnlyTextField.swift; sourceTree = ""; }; - DD964FBE296E76EF007C176F /* WaypointFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaypointFormView.swift; sourceTree = ""; }; + DD964FBE296E76EF007C176F /* WaypointFormMapKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaypointFormMapKit.swift; sourceTree = ""; }; DD964FC029724F6D007C176F /* MeshtasticDataModelV6.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV6.xcdatamodel; sourceTree = ""; }; DD964FC1297272AE007C176F /* WaypointEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaypointEntityExtension.swift; sourceTree = ""; }; DD964FC32974767D007C176F /* MapViewFitExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewFitExtension.swift; sourceTree = ""; }; @@ -437,13 +437,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - C9483F6B2773016700998F6B /* Map */ = { + C9483F6B2773016700998F6B /* MapKitMap */ = { isa = PBXGroup; children = ( C9A7BC0E27759A6800760B50 /* Custom */, - DD964FBE296E76EF007C176F /* WaypointFormView.swift */, + DDDB26472AACD6D1003AFCB7 /* NodeMapMapkit.swift */, + DD964FBE296E76EF007C176F /* WaypointFormMapKit.swift */, ); - path = Map; + path = MapKitMap; sourceTree = ""; }; C9A7BC0E27759A6800760B50 /* Custom */ = { @@ -632,7 +633,6 @@ isa = PBXGroup; children = ( DDB6CCFA2AAF805100945AF6 /* NodeMapSwiftUI.swift */, - DDDB26472AACD6D1003AFCB7 /* NodeMapMapkit.swift */, ); path = Map; sourceTree = ""; @@ -731,7 +731,7 @@ DDC2E18726CE24E40042C5E4 /* Views */ = { isa = PBXGroup; children = ( - C9483F6B2773016700998F6B /* Map */, + C9483F6B2773016700998F6B /* MapKitMap */, DDC2E18D26CE25CB0042C5E4 /* Helpers */, DD47E3D726F2F21A00029299 /* Bluetooth */, DDC2E18B26CE25A70042C5E4 /* Messages */, @@ -1079,7 +1079,7 @@ DDFEB3BB29900C1200EE7472 /* CurrentConditionsCompact.swift in Sources */, DD836AE726F6B38600ABCC23 /* Connect.swift in Sources */, DD5E523F298F5A9E00D21B61 /* AirQualityIndexCompact.swift in Sources */, - DD964FBF296E76EF007C176F /* WaypointFormView.swift in Sources */, + DD964FBF296E76EF007C176F /* WaypointFormMapKit.swift in Sources */, DD3501892852FC3B000FC853 /* Settings.swift in Sources */, DDDB443629F6287000EE2349 /* MapButtons.swift in Sources */, DD5D0A9C2931B9F200F7EA61 /* EthernetModes.swift in Sources */, diff --git a/Meshtastic/Views/Map/Custom/LocalMBTileOverlay.swift b/Meshtastic/Views/MapKitMap/Custom/LocalMBTileOverlay.swift similarity index 100% rename from Meshtastic/Views/Map/Custom/LocalMBTileOverlay.swift rename to Meshtastic/Views/MapKitMap/Custom/LocalMBTileOverlay.swift diff --git a/Meshtastic/Views/Map/Custom/MapButtons.swift b/Meshtastic/Views/MapKitMap/Custom/MapButtons.swift similarity index 100% rename from Meshtastic/Views/Map/Custom/MapButtons.swift rename to Meshtastic/Views/MapKitMap/Custom/MapButtons.swift diff --git a/Meshtastic/Views/Map/Custom/MapViewFitExtension.swift b/Meshtastic/Views/MapKitMap/Custom/MapViewFitExtension.swift similarity index 100% rename from Meshtastic/Views/Map/Custom/MapViewFitExtension.swift rename to Meshtastic/Views/MapKitMap/Custom/MapViewFitExtension.swift diff --git a/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift b/Meshtastic/Views/MapKitMap/Custom/MapViewSwiftUI.swift similarity index 100% rename from Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift rename to Meshtastic/Views/MapKitMap/Custom/MapViewSwiftUI.swift diff --git a/Meshtastic/Views/Nodes/Helpers/Map/NodeMapMapkit.swift b/Meshtastic/Views/MapKitMap/NodeMapMapkit.swift similarity index 99% rename from Meshtastic/Views/Nodes/Helpers/Map/NodeMapMapkit.swift rename to Meshtastic/Views/MapKitMap/NodeMapMapkit.swift index cd1ef380..eeba0318 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/NodeMapMapkit.swift +++ b/Meshtastic/Views/MapKitMap/NodeMapMapkit.swift @@ -145,7 +145,7 @@ struct NodeMapMapkit: View { } .edgesIgnoringSafeArea([.leading, .trailing]) .sheet(item: $waypointCoordinate, content: { wpc in - WaypointFormView(coordinate: wpc) + WaypointFormMapKit(coordinate: wpc) .presentationDetents([.medium, .large]) .presentationDragIndicator(.automatic) }) diff --git a/Meshtastic/Views/Map/WaypointFormView.swift b/Meshtastic/Views/MapKitMap/WaypointFormMapKit.swift similarity index 99% rename from Meshtastic/Views/Map/WaypointFormView.swift rename to Meshtastic/Views/MapKitMap/WaypointFormMapKit.swift index 1b375f4d..722a95d8 100644 --- a/Meshtastic/Views/Map/WaypointFormView.swift +++ b/Meshtastic/Views/MapKitMap/WaypointFormMapKit.swift @@ -8,7 +8,7 @@ import SwiftUI import CoreLocation -struct WaypointFormView: View { +struct WaypointFormMapKit: View { @EnvironmentObject var bleManager: BLEManager @Environment(\.dismiss) private var dismiss diff --git a/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift b/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift index 1b9eeabf..e56299f2 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/NodeMapSwiftUI.swift @@ -99,7 +99,6 @@ struct NodeMapSwiftUI: View { /// Node Annotations ForEach(positionArray, id: \.id) { position in let pf = PositionFlags(rawValue: Int(position.nodePosition?.metadata?.positionFlags ?? 3)) - let formatter = MeasurementFormatter() let headingDegrees = Angle.degrees(Double(position.heading)) Annotation(position.latest ? node.user?.shortName ?? "?": "", coordinate: position.coordinate) { ZStack { @@ -199,91 +198,22 @@ struct NodeMapSwiftUI: View { .padding() } .sheet(isPresented: $isEditingSettings) { - VStack { - Form { - Section(header: Text("Map Options")) { - Picker(selection: $selectedMapLayer, label: Text("")) { - ForEach(MapLayer.allCases, id: \.self) { layer in - if layer != MapLayer.offline { - Text(layer.localized) - } - } - } - .pickerStyle(SegmentedPickerStyle()) - .onChange(of: (selectedMapLayer)) { newMapLayer in - switch selectedMapLayer { - case .standard: - UserDefaults.mapLayer = newMapLayer - mapStyle = MapStyle.standard(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic) - case .hybrid: - UserDefaults.mapLayer = newMapLayer - mapStyle = MapStyle.hybrid(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic) - case .satellite: - UserDefaults.mapLayer = newMapLayer - mapStyle = MapStyle.imagery(elevation: .realistic) - case .offline: - return - } - } - .padding(.top, 5) - .padding(.bottom, 5) - Toggle(isOn: $showNodeHistory) { - Label("Node History", systemImage: "building.columns.fill") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onTapGesture { - self.showNodeHistory.toggle() - UserDefaults.enableMapNodeHistoryPins = self.showNodeHistory - } - Toggle(isOn: $showRouteLines) { - Label("Route Lines", systemImage: "road.lanes") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onTapGesture { - self.showRouteLines.toggle() - UserDefaults.enableMapRouteLines = self.showRouteLines - } - Toggle(isOn: $showConvexHull) { - Label("Convex Hull", systemImage: "button.angledbottom.horizontal.right") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onTapGesture { - self.showConvexHull.toggle() - UserDefaults.enableMapConvexHull = self.showConvexHull - } - Toggle(isOn: $showTraffic) { - Label("Traffic", systemImage: "car") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onTapGesture { - self.showTraffic.toggle() - UserDefaults.enableMapTraffic = self.showTraffic - } - Toggle(isOn: $showPointsOfInterest) { - Label("Points of Interest", systemImage: "mappin.and.ellipse") - } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - .onTapGesture { - self.showPointsOfInterest.toggle() - UserDefaults.enableMapPointsOfInterest = self.showPointsOfInterest - } + MapSettingsForm(nodeHistory: $showNodeHistory, routeLines: $showRouteLines, convexHull: $showConvexHull, traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer) + .onChange(of: (selectedMapLayer)) { newMapLayer in + switch selectedMapLayer { + case .standard: + UserDefaults.mapLayer = newMapLayer + mapStyle = MapStyle.standard(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic) + case .hybrid: + UserDefaults.mapLayer = newMapLayer + mapStyle = MapStyle.hybrid(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic) + case .satellite: + UserDefaults.mapLayer = newMapLayer + mapStyle = MapStyle.imagery(elevation: .realistic) + case .offline: + return } } - #if targetEnvironment(macCatalyst) - Button { - isEditingSettings = false - } label: { - Label("close", systemImage: "xmark") - } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding() - #endif - } - .presentationDetents([.fraction(0.4), .medium]) - .presentationDragIndicator(.visible) - } .onChange(of: node) { let mostRecent = node.positions?.lastObject as? PositionEntity diff --git a/Meshtastic/Views/Nodes/Helpers/MapSettingsForm.swift b/Meshtastic/Views/Nodes/Helpers/MapSettingsForm.swift index 3093388b..400ef2e5 100644 --- a/Meshtastic/Views/Nodes/Helpers/MapSettingsForm.swift +++ b/Meshtastic/Views/Nodes/Helpers/MapSettingsForm.swift @@ -13,12 +13,12 @@ import MapKit @available(iOS 17.0, macOS 14.0, *) struct MapSettingsForm: View { @Environment(\.dismiss) private var dismiss - @State var nodeHistory = false - @State var routeLines = false - @State var convexHull = false - @State var traffic: Bool = false - @State var pointsOfInterest: Bool = false - @State var mapLayer: MapLayer = .standard + @Binding var nodeHistory: Bool + @Binding var routeLines: Bool + @Binding var convexHull: Bool + @Binding var traffic: Bool + @Binding var pointsOfInterest: Bool + @Binding var mapLayer: MapLayer var body: some View { @@ -35,6 +35,9 @@ struct MapSettingsForm: View { .pickerStyle(SegmentedPickerStyle()) .padding(.top, 5) .padding(.bottom, 5) + .onChange(of: mapLayer) { newMapLayer in + UserDefaults.mapLayer = newMapLayer + } Toggle(isOn: $nodeHistory) { Label("Node History", systemImage: "building.columns.fill") } @@ -78,19 +81,18 @@ struct MapSettingsForm: View { } } #if targetEnvironment(macCatalyst) - Button { - dismiss() - } label: { - Label("close", systemImage: "xmark") - } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding() +Spacer() + Button { + dismiss() + } label: { + Label("close", systemImage: "xmark") + } + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.large) #endif } - .presentationDetents([.fraction(0.60)]) - //.presentationDetents([.medium, .large]) - .presentationDragIndicator(.automatic) + .presentationDetents([.fraction(0.45), .fraction(0.65)]) + .presentationDragIndicator(.visible) } } diff --git a/Meshtastic/Views/Nodes/Helpers/PositionPopover.swift b/Meshtastic/Views/Nodes/Helpers/PositionPopover.swift index 62166f89..12af8f4b 100644 --- a/Meshtastic/Views/Nodes/Helpers/PositionPopover.swift +++ b/Meshtastic/Views/Nodes/Helpers/PositionPopover.swift @@ -9,10 +9,12 @@ import SwiftUI import MapKit struct PositionPopover: View { + @Environment(\.dismiss) private var dismiss var position: PositionEntity + var popover: Bool = true let distanceFormatter = MKDistanceFormatter() var body: some View { - VStack (alignment: .leading) { + VStack { HStack { CircleText(text: position.nodePosition?.user?.shortName ?? "?", color: Color(UIColor(hex: UInt32(position.nodePosition?.user?.num ?? 0))), circleSize: 65) Spacer() @@ -129,6 +131,20 @@ struct PositionPopover: View { } } .padding(.top) + if !popover { +#if targetEnvironment(macCatalyst) + Spacer() + Button { + dismiss() + } label: { + Label("close", systemImage: "xmark") + } + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.large) + .padding(.bottom) +#endif + } } .presentationDetents([.fraction(0.45), .medium]) .presentationDragIndicator(.visible) diff --git a/Meshtastic/Views/Nodes/MeshMap.swift b/Meshtastic/Views/Nodes/MeshMap.swift index 484e12bc..2d07971a 100644 --- a/Meshtastic/Views/Nodes/MeshMap.swift +++ b/Meshtastic/Views/Nodes/MeshMap.swift @@ -52,6 +52,10 @@ struct MeshMap: View { private var waypoints: FetchedResults var body: some View { + + let lineCoords = Array(positions).compactMap({(position) -> CLLocationCoordinate2D in + return position.nodeCoordinate ?? LocationHelper.DefaultLocation + }) NavigationStack { ZStack { MapReader { reader in @@ -71,8 +75,21 @@ struct MeshMap: View { } } } + /// Convex Hull + if showConvexHull { + let hull = lineCoords.getConvexHull() + MapPolygon(coordinates: hull) + .stroke(.blue, lineWidth: 3) + .foregroundStyle(.indigo.opacity(0.4)) + //.stroke(Color(nodeColor.darker()), lineWidth: 3) + //.foregroundStyle(Color(nodeColor).opacity(0.4)) + } + /// Position Annotations ForEach(Array(positions), id: \.id) { position in + let pf = PositionFlags(rawValue: Int(position.nodePosition?.metadata?.positionFlags ?? 3)) + /// Node Color from node.num + let nodeColor = UIColor(hex: UInt32(position.nodePosition?.num ?? 0)) Annotation(position.nodePosition?.user?.longName ?? "?", coordinate: position.coordinate) { ZStack { let nodeColor = UIColor(hex: UInt32(position.nodePosition?.num ?? 0)) @@ -99,22 +116,131 @@ struct MeshMap: View { selectedPosition = (selectedPosition == position ? nil : position) } } + // routeLines + if showRouteLines { + let positionArray = position.nodePosition?.positions?.array as? [PositionEntity] ?? [] + let routeCoords = positionArray.compactMap({(position) -> CLLocationCoordinate2D in + return position.nodeCoordinate ?? LocationHelper.DefaultLocation + }) + if showRouteLines { + let gradient = LinearGradient( + colors: [Color(nodeColor.lighter().lighter()), Color(nodeColor.lighter()), Color(nodeColor)], + startPoint: .leading, endPoint: .trailing + ) + let dashed = StrokeStyle( + lineWidth: 3, + lineCap: .round, lineJoin: .round, dash: [10, 10] + ) + MapPolyline(coordinates: routeCoords) + .stroke(gradient, style: dashed) + } + } // Node History + if showNodeHistory { + ForEach(position.nodePosition!.positions!.reversed() as! [PositionEntity], id: \.self) { (mappin: PositionEntity) in + Annotation(position.latest ? position.nodePosition?.user?.shortName ?? "?": "", coordinate: position.coordinate) { + ZStack { + Circle() + .fill(Color(UIColor(hex: UInt32(position.nodePosition?.num ?? 0)))) + .strokeBorder(Color(UIColor(hex: UInt32(position.nodePosition?.num ?? 0))).isLight() ? .black : .white ,lineWidth: 2) + .frame(width: 12, height: 12) + + } + } + .annotationTitles(.hidden) + .annotationSubtitles(.hidden) + } + } } } } } - .ignoresSafeArea(.all, edges: [.top, .leading, .trailing]) - .frame(maxHeight: .infinity) -// .popover(item: $selectedPosition) { selection in -// PositionPopover(position: selection) -// .padding() -// .opacity(0.8) -// .presentationCompactAdaptation(.sheet) -// } + .mapScope(mapScope) + .mapStyle(mapStyle) + .mapControls { + MapScaleView(scope: mapScope) + .mapControlVisibility(.visible) + if showUserLocation { + MapUserLocationButton(scope: mapScope) + .mapControlVisibility(.visible) + } + MapPitchToggle(scope: mapScope) + .mapControlVisibility(.visible) + MapCompass(scope: mapScope) + .mapControlVisibility(.visible) + } + .controlSize(.regular) .sheet(item: $selectedPosition) { selection in - PositionPopover(position: selection) + PositionPopover(position: selection, popover: false) .padding() } + .sheet(item: $selectedWaypoint) { selection in + WaypointPopover(waypoint: selection) + .padding() + } + .sheet(isPresented: $isEditingSettings) { + MapSettingsForm(nodeHistory: $showNodeHistory, routeLines: $showRouteLines, convexHull: $showConvexHull, traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer) + } + .onChange(of: (selectedMapLayer)) { newMapLayer in + switch selectedMapLayer { + case .standard: + UserDefaults.mapLayer = newMapLayer + mapStyle = MapStyle.standard(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic) + case .hybrid: + UserDefaults.mapLayer = newMapLayer + mapStyle = MapStyle.hybrid(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic) + case .satellite: + UserDefaults.mapLayer = newMapLayer + mapStyle = MapStyle.imagery(elevation: .realistic) + case .offline: + return + } + } + .safeAreaInset(edge: .bottom, alignment: UIDevice.current.userInterfaceIdiom == .phone ? .leading : .trailing) { + HStack { + Button(action: { + withAnimation { + isEditingSettings = !isEditingSettings + } + }) { + Image(systemName: isEditingSettings ? "info.circle.fill" : "info.circle") + .padding(.vertical, 5) + } + .tint(Color(UIColor.secondarySystemBackground)) + .foregroundColor(.accentColor) + .buttonStyle(.borderedProminent) + /// Show / Hide Waypoints Button + if waypoints.count > 0 { + + 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) + } + /// Look Around Button + if self.scene != nil { + Button(action: { + withAnimation { + isLookingAround = !isLookingAround + } + }) { + Image(systemName: isLookingAround ? "binoculars.fill" : "binoculars") + .padding(.vertical, 5) + } + .tint(Color(UIColor.secondarySystemBackground)) + .foregroundColor(.accentColor) + .buttonStyle(.borderedProminent) + } + } + .controlSize(.regular) + .padding(5) + } } .navigationTitle("Mesh Map") .navigationBarItems(leading: @@ -126,12 +252,22 @@ struct MeshMap: View { name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?") }) - .onAppear(perform: { + .onAppear { UIApplication.shared.isIdleTimerDisabled = true if self.bleManager.context == nil { self.bleManager.context = context } - }) + switch selectedMapLayer { + case .standard: + mapStyle = MapStyle.standard(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic) + case .hybrid: + mapStyle = MapStyle.hybrid(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic) + case .satellite: + mapStyle = MapStyle.imagery(elevation: .realistic) + case .offline: + mapStyle = MapStyle.hybrid(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic) + } + } .onDisappear(perform: { UIApplication.shared.isIdleTimerDisabled = false }) diff --git a/Meshtastic/Views/Nodes/NodeMap.swift b/Meshtastic/Views/Nodes/NodeMap.swift index a41f891c..109fc225 100644 --- a/Meshtastic/Views/Nodes/NodeMap.swift +++ b/Meshtastic/Views/Nodes/NodeMap.swift @@ -76,7 +76,7 @@ struct NodeMap: View { .ignoresSafeArea(.all, edges: [.top, .leading, .trailing]) .frame(maxHeight: .infinity) .sheet(item: $waypointCoordinate, content: { wpc in - WaypointFormView(coordinate: wpc) + WaypointFormMapKit(coordinate: wpc) .presentationDetents([.medium, .large]) .presentationDragIndicator(.automatic) }) diff --git a/Meshtastic/Views/Settings/UserConfig.swift b/Meshtastic/Views/Settings/UserConfig.swift index b3fe4a49..c9d64c05 100644 --- a/Meshtastic/Views/Settings/UserConfig.swift +++ b/Meshtastic/Views/Settings/UserConfig.swift @@ -121,7 +121,7 @@ struct UserConfig: View { HStack { Image(systemName: "antenna.radiowaves.left.and.right") .foregroundColor(.accentColor) - Stepper("\(txPower)db Transmit Power", value: $txPower, in: 0...30, step: 1) + Stepper("\(txPower)db Transmit Power", value: $txPower, in: 1...30, step: 1) .padding(5) } }