From e0073ebdc89b1ce87fc12506112ff7e7809ae6f3 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sat, 20 Jan 2024 22:49:55 -0800 Subject: [PATCH] Solid lines for routes --- Meshtastic/Helpers/LocationsHandler.swift | 57 +- Meshtastic/Views/Nodes/MeshMap.swift | 9 +- .../Settings/Config/Module/MQTTConfig.swift | 4 +- Meshtastic/Views/Settings/Firmware.swift | 3 +- Meshtastic/Views/Settings/RouteRecorder.swift | 572 +++++++++--------- Meshtastic/Views/Settings/Routes.swift | 6 +- Meshtastic/Views/Settings/Settings.swift | 16 +- 7 files changed, 335 insertions(+), 332 deletions(-) diff --git a/Meshtastic/Helpers/LocationsHandler.swift b/Meshtastic/Helpers/LocationsHandler.swift index 4742914a..fec450ff 100644 --- a/Meshtastic/Helpers/LocationsHandler.swift +++ b/Meshtastic/Helpers/LocationsHandler.swift @@ -18,6 +18,7 @@ import CoreLocation var enableSmartPosition: Bool @Published var locationsArray: [CLLocation] + @Published var lastLocation: CLLocation @Published var isStationary = false @Published var count = 0 @Published var isRecording = false @@ -42,6 +43,7 @@ import CoreLocation private init() { self.manager = CLLocationManager() // Creating a location manager instance is safe to call here in `MainActor`. locationsArray = [CLLocation]() + lastLocation = CLLocation() enableSmartPosition = true } @@ -64,7 +66,11 @@ import CoreLocation locationAdded = addLocation(loc) //print("Added Location \(self.count): \(loc)") } else { - locationsArray.append(loc) + if !isRecording { + lastLocation = loc + } else { + locationsArray.append(loc) + } locationAdded = true } if locationAdded { @@ -99,16 +105,14 @@ import CoreLocation return false } if isRecording { - if let lastLocation = locationsArray.last { - let distance = location.distance(from: lastLocation) - let gain = location.altitude - lastLocation.altitude - distanceTraveled += distance - if gain > 0 { - elevationGain += gain - } + let distance = location.distance(from: lastLocation) + let gain = location.altitude - lastLocation.altitude + distanceTraveled += distance + if gain > 0 { + elevationGain += gain } + locationsArray.append(location) } - locationsArray.append(location) return true } @@ -116,26 +120,23 @@ import CoreLocation static var satsInView: Int { var sats = 0 - if let newLocation = shared.locationsArray.last { - sats = 1 - if newLocation.verticalAccuracy > 0 { - sats = 4 - if 0...5 ~= newLocation.horizontalAccuracy { - sats = 12 - } else if 6...15 ~= newLocation.horizontalAccuracy { - sats = 10 - } else if 16...30 ~= newLocation.horizontalAccuracy { - sats = 9 - } else if 31...45 ~= newLocation.horizontalAccuracy { - sats = 7 - } else if 46...60 ~= newLocation.horizontalAccuracy { - sats = 5 - } - } else if newLocation.verticalAccuracy < 0 && 60...300 ~= newLocation.horizontalAccuracy { - sats = 3 - } else if newLocation.verticalAccuracy < 0 && newLocation.horizontalAccuracy > 300 { - sats = 2 + if shared.lastLocation.verticalAccuracy > 0 { + sats = 4 + if 0...5 ~= shared.lastLocation.horizontalAccuracy { + sats = 12 + } else if 6...15 ~= shared.lastLocation.horizontalAccuracy { + sats = 10 + } else if 16...30 ~= shared.lastLocation.horizontalAccuracy { + sats = 9 + } else if 31...45 ~= shared.lastLocation.horizontalAccuracy { + sats = 7 + } else if 46...60 ~= shared.lastLocation.horizontalAccuracy { + sats = 5 } + } else if shared.lastLocation.verticalAccuracy < 0 && 60...300 ~= shared.lastLocation.horizontalAccuracy { + sats = 3 + } else if shared.lastLocation.verticalAccuracy < 0 && shared.lastLocation.horizontalAccuracy > 300 { + sats = 2 } return sats } diff --git a/Meshtastic/Views/Nodes/MeshMap.swift b/Meshtastic/Views/Nodes/MeshMap.swift index 7dd7d8db..3cee7eb3 100644 --- a/Meshtastic/Views/Nodes/MeshMap.swift +++ b/Meshtastic/Views/Nodes/MeshMap.swift @@ -150,12 +150,12 @@ struct MeshMap: View { } } .annotationTitles(.automatic) - let dashed = StrokeStyle( + let solid = StrokeStyle( lineWidth: 3, - lineCap: .round, lineJoin: .round, dash: [7, 10] + lineCap: .round, lineJoin: .round ) MapPolyline(coordinates: routeCoords) - .stroke(Color(UIColor(hex: UInt32(route.color))), style: dashed) + .stroke(Color(UIColor(hex: UInt32(route.color))), style: solid) } /// Node Route Lines @@ -275,7 +275,8 @@ struct MeshMap: View { print("Waypoint not found") return } - position = .camera(MapCamera(centerCoordinate: waypoint.coordinate, distance: 150, heading: 0, pitch: 60)) + showWaypoints = true + position = .camera(MapCamera(centerCoordinate: waypoint.coordinate, distance: 300, heading: 0, pitch: 60)) } } .onChange(of: (selectedMapLayer)) { newMapLayer in diff --git a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift index ce8c52b5..be78fb96 100644 --- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift @@ -24,6 +24,8 @@ struct MQTTConfig: View { @State var tlsEnabled = true @State var root = "msh" @State var mqttConnected: Bool = false + + var body: some View { VStack { @@ -250,7 +252,7 @@ struct MQTTConfig: View { .navigationTitle("mqtt.config") .navigationBarItems(trailing: ZStack { - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?") + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?", mqttProxyConnected: bleManager.mqttProxyConnected) }) .onAppear { if self.bleManager.context == nil { diff --git a/Meshtastic/Views/Settings/Firmware.swift b/Meshtastic/Views/Settings/Firmware.swift index c0141523..94894d57 100644 --- a/Meshtastic/Views/Settings/Firmware.swift +++ b/Meshtastic/Views/Settings/Firmware.swift @@ -112,8 +112,7 @@ struct Firmware: View { if bleManager.sendEnterDfuMode(fromUser: connectedNode!.user!, toUser: node!.user!) { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - bleManager.automaticallyReconnect = false - bleManager.disconnectPeripheral() + bleManager.disconnectPeripheral(reconnect: false) } } else { print("Enter DFU Failed") diff --git a/Meshtastic/Views/Settings/RouteRecorder.swift b/Meshtastic/Views/Settings/RouteRecorder.swift index 601f2a49..342d7aca 100644 --- a/Meshtastic/Views/Settings/RouteRecorder.swift +++ b/Meshtastic/Views/Settings/RouteRecorder.swift @@ -1,289 +1,289 @@ +//// +//// Routes.swift +//// Meshtastic +//// +//// Created by Garth Vander Houwen on 11/21/23. +//// // -// Routes.swift -// Meshtastic +//import SwiftUI +//import CoreData +//import MapKit +//import CoreLocation +//import CoreMotion // -// Created by Garth Vander Houwen on 11/21/23. +//@available(iOS 17.0, macOS 14.0, *) +//struct RouteRecorder: View { +// +// @ObservedObject var locationsHandler: LocationsHandler = LocationsHandler.shared +// @Environment(\.managedObjectContext) var context +// @State private var position: MapCameraPosition = .userLocation(followsHeading: true, fallback: .automatic) +// //@State var mapStyle: MapStyle = MapStyle.hybrid(elevation: .realistic, pointsOfInterest: .all, showsTraffic: true) +// @State var mapStyle: MapStyle = MapStyle.standard(elevation: .realistic) +// @State var isShowingDetails = false +// @Namespace var namespace +// @Namespace var routerecorderscope +// @State var recording: RouteEntity? +// @State var color: Color = .blue +// +// var body: some View { +// VStack { +// ZStack { +// Map(position: $position, scope: routerecorderscope) { +// UserAnnotation() +// /// Route Lines +// let lineCoords = locationsHandler.locationsArray.compactMap({(position) -> CLLocationCoordinate2D in +// return position.coordinate +// }) +// +// let gradient = LinearGradient( +// colors: [color], +// startPoint: .leading, endPoint: .trailing +// ) +// let dashed = StrokeStyle( +// lineWidth: 3, +// lineCap: .round, lineJoin: .round, dash: [10, 10] +// ) +// MapPolyline(coordinates: lineCoords) +// .stroke(gradient, style: dashed) // - -import SwiftUI -import CoreData -import MapKit -import CoreLocation -import CoreMotion - -@available(iOS 17.0, macOS 14.0, *) -struct RouteRecorder: View { - - @ObservedObject var locationsHandler: LocationsHandler = LocationsHandler.shared - @Environment(\.managedObjectContext) var context - @State private var position: MapCameraPosition = .userLocation(followsHeading: true, fallback: .automatic) - //@State var mapStyle: MapStyle = MapStyle.hybrid(elevation: .realistic, pointsOfInterest: .all, showsTraffic: true) - @State var mapStyle: MapStyle = MapStyle.standard(elevation: .realistic) - @State var isShowingDetails = false - @Namespace var namespace - @Namespace var routerecorderscope - @State var recording: RouteEntity? - @State var color: Color = .blue - - var body: some View { - VStack { - ZStack { - Map(position: $position, scope: routerecorderscope) { - UserAnnotation() - /// Route Lines - let lineCoords = locationsHandler.locationsArray.compactMap({(position) -> CLLocationCoordinate2D in - return position.coordinate - }) - - let gradient = LinearGradient( - colors: [color], - startPoint: .leading, endPoint: .trailing - ) - let dashed = StrokeStyle( - lineWidth: 3, - lineCap: .round, lineJoin: .round, dash: [10, 10] - ) - MapPolyline(coordinates: lineCoords) - .stroke(gradient, style: dashed) - - } - .mapStyle(mapStyle) - } - .mapScope(routerecorderscope) - .safeAreaInset(edge: .bottom) { - ZStack { - VStack { - HStack(spacing: 10) { - Spacer() - - Button { - isShowingDetails = true - } label: { - Image(systemName: locationsHandler.isRecording ? "record.circle.fill" : "record.circle") - .font(.system(size: 72)) - .symbolRenderingMode(.multicolor) - .foregroundColor(.red) - } - .buttonStyle(.bordered) - .foregroundColor(.red) - .buttonBorderShape(.circle) - .matchedGeometryEffect(id: "Details Button", in: namespace) - - Spacer() - } - } - } - .padding() - } - .sheet(isPresented: $isShowingDetails) { - NavigationStack { - VStack { - if locationsHandler.isRecording { - HStack (alignment: .center) { - Image(systemName: "record.circle.fill") - .symbolRenderingMode(.multicolor) - .font(.title) - .foregroundColor(.red) - Text("Recording route") - .font(.title) - Spacer() - Text("\(locationsHandler.count)") - .foregroundColor(.red) - .font(.title2) - } - .padding() - } else if locationsHandler.isRecordingPaused { - HStack (alignment: .center) { - - Image(systemName: "playpause") - .symbolRenderingMode(.multicolor) - .font(.title3) - .foregroundColor(.red) - Text("Route recording paused") - .font(.title) - } - .padding(.top) - } - - if locationsHandler.isRecording || locationsHandler.isRecordingPaused { - Divider() - HStack { - VStack { - Text(locationsHandler.recordingStarted ?? Date(), style: .timer) - .font(.title) - .fixedSize() - Text("Time") - .font(.callout) - .fixedSize() - } - .padding(.horizontal) - Divider() - VStack { - let distance = Measurement(value: locationsHandler.distanceTraveled, unit: UnitLength.meters) - Text("\(distance.formatted())") - .font(.title) - .fixedSize() - Text("Distance") - .font(.callout) - .fixedSize() - } - .padding(.horizontal) - Divider() - VStack { - let gain = Measurement(value: locationsHandler.elevationGain, unit: UnitLength.meters) - Text(gain.formatted()) - .font(.title) - Text("Elev. Gain") - .font(.callout) - } - .padding(.horizontal) - } - .frame(maxHeight: 90) - } - Divider() - VStack(alignment: .leading) { - List { - GPSStatus(largeFont: .body, smallFont: .callout) - } - .listStyle(.plain) - HStack { - Spacer() - if !locationsHandler.isRecording && !locationsHandler.isRecordingPaused { - /// We are not recording or paused, show start recording button - Button { - locationsHandler.isRecording = true - locationsHandler.count = 0 - locationsHandler.distanceTraveled = 0.0 - locationsHandler.elevationGain = 0.0 - locationsHandler.locationsArray.removeAll() - locationsHandler.recordingStarted = Date() - let newRoute = RouteEntity(context: context) - newRoute.name = String("Route Recording") - newRoute.id = Int32.random(in: Int32(Int8.max) ... Int32.max) - newRoute.color = Int64(UIColor.random.hex) - newRoute.date = Date() - newRoute.enabled = false - color = Color(UIColor(hex: UInt32(newRoute.color))) - self.recording = newRoute - do { - try context.save() - print("💾 Saved a new route") - } catch { - context.rollback() - let nsError = error as NSError - print("💥 Error Saving RouteEntity from the Route Recorder \(nsError)") - } - } label: { - Label("start", systemImage: "play") - } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding(.bottom) - - } else if locationsHandler.isRecording { - /// We are recording show pause button - Button { - locationsHandler.isRecording = false - locationsHandler.isRecordingPaused = true - } label: { - Label("pause", systemImage: "pause") - } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding(.bottom) - } else if locationsHandler.isRecordingPaused { - /// We are paused show resume button - Button { - locationsHandler.isRecording = true - locationsHandler.isRecordingPaused = false - } label: { - Label("resume", systemImage: "playpause") - } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding(.bottom) - } - - if locationsHandler.isRecording || locationsHandler.isRecordingPaused { - /// We are recording or paused, show finish button - Button { - locationsHandler.isRecording = false - locationsHandler.isRecordingPaused = false - locationsHandler.distanceTraveled = 0.0 - locationsHandler.elevationGain = 0.0 - locationsHandler.locationsArray.removeAll() - locationsHandler.recordingStarted = nil - if let rec = recording { - rec.enabled = true - context.refresh(rec, mergeChanges:true) - } - - do { - try context.save() - print("💾 Saved a route finish") - } catch { - context.rollback() - let nsError = error as NSError - print("💥 Error Saving RouteEntity from the Route Recorder \(nsError)") - } - } label: { - Label("finish", systemImage: "flag.checkered") - } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding(.bottom) - } -#if targetEnvironment(macCatalyst) - Button(role: .cancel) { - isShowingDetails = false - } label: { - Label("close", systemImage: "xmark") - } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.large) - .padding(.bottom) -#endif - Spacer() - } - - } - } - } - .presentationDetents([.fraction(0.30), .fraction(0.65)]) - .presentationDragIndicator(.hidden) - .interactiveDismissDisabled(false) - .onChange(of: locationsHandler.locationsArray.last) { newLoc in - if locationsHandler.isRecording { - if let loc = newLoc { - if recording != nil { - let locationEntity = LocationEntity(context: context) - locationEntity.routeLocation = recording - locationEntity.id = Int32(locationsHandler.count) - locationEntity.altitude = Int32(loc.altitude) - locationEntity.heading = Int32(loc.course) - locationEntity.speed = Int32(loc.speed) - locationEntity.latitudeI = Int32(loc.coordinate.latitude * 1e7) - locationEntity.longitudeI = Int32(loc.coordinate.longitude * 1e7) - do { - try context.save() - print("💾 Saved a new route location") - //print("💾 Updated Canned Messages Messages For: \(fetchedNode[0].num)") - } catch { - context.rollback() - let nsError = error as NSError - print("💥 Error Saving LocationEntity from the Route Recorder \(nsError)") - } - } - } - } - } - } - } - .ignoresSafeArea(.all, edges: [.top, .leading, .trailing]) - } -} +// } +// .mapStyle(mapStyle) +// } +// .mapScope(routerecorderscope) +// .safeAreaInset(edge: .bottom) { +// ZStack { +// VStack { +// HStack(spacing: 10) { +// Spacer() +// +// Button { +// isShowingDetails = true +// } label: { +// Image(systemName: locationsHandler.isRecording ? "record.circle.fill" : "record.circle") +// .font(.system(size: 72)) +// .symbolRenderingMode(.multicolor) +// .foregroundColor(.red) +// } +// .buttonStyle(.bordered) +// .foregroundColor(.red) +// .buttonBorderShape(.circle) +// .matchedGeometryEffect(id: "Details Button", in: namespace) +// +// Spacer() +// } +// } +// } +// .padding() +// } +// .sheet(isPresented: $isShowingDetails) { +// NavigationStack { +// VStack { +// if locationsHandler.isRecording { +// HStack (alignment: .center) { +// Image(systemName: "record.circle.fill") +// .symbolRenderingMode(.multicolor) +// .font(.title) +// .foregroundColor(.red) +// Text("Recording route") +// .font(.title) +// Spacer() +// Text("\(locationsHandler.count)") +// .foregroundColor(.red) +// .font(.title2) +// } +// .padding() +// } else if locationsHandler.isRecordingPaused { +// HStack (alignment: .center) { +// +// Image(systemName: "playpause") +// .symbolRenderingMode(.multicolor) +// .font(.title3) +// .foregroundColor(.red) +// Text("Route recording paused") +// .font(.title) +// } +// .padding(.top) +// } +// +// if locationsHandler.isRecording || locationsHandler.isRecordingPaused { +// Divider() +// HStack { +// VStack { +// Text(locationsHandler.recordingStarted ?? Date(), style: .timer) +// .font(.title) +// .fixedSize() +// Text("Time") +// .font(.callout) +// .fixedSize() +// } +// .padding(.horizontal) +// Divider() +// VStack { +// let distance = Measurement(value: locationsHandler.distanceTraveled, unit: UnitLength.meters) +// Text("\(distance.formatted())") +// .font(.title) +// .fixedSize() +// Text("Distance") +// .font(.callout) +// .fixedSize() +// } +// .padding(.horizontal) +// Divider() +// VStack { +// let gain = Measurement(value: locationsHandler.elevationGain, unit: UnitLength.meters) +// Text(gain.formatted()) +// .font(.title) +// Text("Elev. Gain") +// .font(.callout) +// } +// .padding(.horizontal) +// } +// .frame(maxHeight: 90) +// } +// Divider() +// VStack(alignment: .leading) { +// List { +// GPSStatus(largeFont: .body, smallFont: .callout) +// } +// .listStyle(.plain) +// HStack { +// Spacer() +// if !locationsHandler.isRecording && !locationsHandler.isRecordingPaused { +// /// We are not recording or paused, show start recording button +// Button { +// locationsHandler.isRecording = true +// locationsHandler.count = 0 +// locationsHandler.distanceTraveled = 0.0 +// locationsHandler.elevationGain = 0.0 +// locationsHandler.locationsArray.removeAll() +// locationsHandler.recordingStarted = Date() +// let newRoute = RouteEntity(context: context) +// newRoute.name = String("Route Recording") +// newRoute.id = Int32.random(in: Int32(Int8.max) ... Int32.max) +// newRoute.color = Int64(UIColor.random.hex) +// newRoute.date = Date() +// newRoute.enabled = false +// color = Color(UIColor(hex: UInt32(newRoute.color))) +// self.recording = newRoute +// do { +// try context.save() +// print("💾 Saved a new route") +// } catch { +// context.rollback() +// let nsError = error as NSError +// print("💥 Error Saving RouteEntity from the Route Recorder \(nsError)") +// } +// } label: { +// Label("start", systemImage: "play") +// } +// .buttonStyle(.bordered) +// .buttonBorderShape(.capsule) +// .controlSize(.large) +// .padding(.bottom) +// +// } else if locationsHandler.isRecording { +// /// We are recording show pause button +// Button { +// locationsHandler.isRecording = false +// locationsHandler.isRecordingPaused = true +// } label: { +// Label("pause", systemImage: "pause") +// } +// .buttonStyle(.bordered) +// .buttonBorderShape(.capsule) +// .controlSize(.large) +// .padding(.bottom) +// } else if locationsHandler.isRecordingPaused { +// /// We are paused show resume button +// Button { +// locationsHandler.isRecording = true +// locationsHandler.isRecordingPaused = false +// } label: { +// Label("resume", systemImage: "playpause") +// } +// .buttonStyle(.bordered) +// .buttonBorderShape(.capsule) +// .controlSize(.large) +// .padding(.bottom) +// } +// +// if locationsHandler.isRecording || locationsHandler.isRecordingPaused { +// /// We are recording or paused, show finish button +// Button { +// locationsHandler.isRecording = false +// locationsHandler.isRecordingPaused = false +// locationsHandler.distanceTraveled = 0.0 +// locationsHandler.elevationGain = 0.0 +// locationsHandler.locationsArray.removeAll() +// locationsHandler.recordingStarted = nil +// if let rec = recording { +// rec.enabled = true +// context.refresh(rec, mergeChanges:true) +// } +// +// do { +// try context.save() +// print("💾 Saved a route finish") +// } catch { +// context.rollback() +// let nsError = error as NSError +// print("💥 Error Saving RouteEntity from the Route Recorder \(nsError)") +// } +// } label: { +// Label("finish", systemImage: "flag.checkered") +// } +// .buttonStyle(.bordered) +// .buttonBorderShape(.capsule) +// .controlSize(.large) +// .padding(.bottom) +// } +//#if targetEnvironment(macCatalyst) +// Button(role: .cancel) { +// isShowingDetails = false +// } label: { +// Label("close", systemImage: "xmark") +// } +// .buttonStyle(.bordered) +// .buttonBorderShape(.capsule) +// .controlSize(.large) +// .padding(.bottom) +//#endif +// Spacer() +// } +// +// } +// } +// } +// .presentationDetents([.fraction(0.30), .fraction(0.65)]) +// .presentationDragIndicator(.hidden) +// .interactiveDismissDisabled(false) +// .onChange(of: locationsHandler.locationsArray.last) { newLoc in +// if locationsHandler.isRecording { +// if let loc = newLoc { +// if recording != nil { +// let locationEntity = LocationEntity(context: context) +// locationEntity.routeLocation = recording +// locationEntity.id = Int32(locationsHandler.count) +// locationEntity.altitude = Int32(loc.altitude) +// locationEntity.heading = Int32(loc.course) +// locationEntity.speed = Int32(loc.speed) +// locationEntity.latitudeI = Int32(loc.coordinate.latitude * 1e7) +// locationEntity.longitudeI = Int32(loc.coordinate.longitude * 1e7) +// do { +// try context.save() +// print("💾 Saved a new route location") +// //print("💾 Updated Canned Messages Messages For: \(fetchedNode[0].num)") +// } catch { +// context.rollback() +// let nsError = error as NSError +// print("💥 Error Saving LocationEntity from the Route Recorder \(nsError)") +// } +// } +// } +// } +// } +// } +// } +// .ignoresSafeArea(.all, edges: [.top, .leading, .trailing]) +// } +//} diff --git a/Meshtastic/Views/Settings/Routes.swift b/Meshtastic/Views/Settings/Routes.swift index 6c1de5a0..14e01d0f 100644 --- a/Meshtastic/Views/Settings/Routes.swift +++ b/Meshtastic/Views/Settings/Routes.swift @@ -181,12 +181,12 @@ struct Routes: View { } } .annotationTitles(.automatic) - let dashed = StrokeStyle( + let solid = StrokeStyle( lineWidth: 3, - lineCap: .round, lineJoin: .round, dash: [7, 10] + lineCap: .round, lineJoin: .round ) MapPolyline(coordinates: lineCoords) - .stroke(Color(UIColor(hex: UInt32(selectedRoute?.color ?? 0))), style: dashed) + .stroke(Color(UIColor(hex: UInt32(selectedRoute?.color ?? 0))), style: solid) } .frame(maxWidth: .infinity, maxHeight: .infinity) .safeAreaInset(edge: .bottom, alignment: UIDevice.current.userInterfaceIdiom == .phone ? .leading : .trailing) { diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index 87d23bd3..66d1e02e 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -69,14 +69,14 @@ struct Settings: View { Text("routes") } .tag(SettingsSidebar.routes) - NavigationLink { - RouteRecorder() - } label: { - Image(systemName: "record.circle") - .symbolRenderingMode(.hierarchical) - Text("route.recorder") - } - .tag(SettingsSidebar.routeRecorder) +// NavigationLink { +// RouteRecorder() +// } label: { +// Image(systemName: "record.circle") +// .symbolRenderingMode(.hierarchical) +// Text("route.recorder") +// } +// .tag(SettingsSidebar.routeRecorder) } let node = nodes.first(where: { $0.num == preferredNodeNum })