diff --git a/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift b/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift index 62e834b0..0a5edf70 100644 --- a/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift +++ b/Meshtastic/Views/Map/Custom/MapViewSwiftUI.swift @@ -160,45 +160,6 @@ struct MapViewSwiftUI: UIViewRepresentable { } } } - private func setGeoJsonOverlay(mapView: MKMapView) { - guard let geoJsonFileUrl = URL(string: "https://raw.githubusercontent.com/johan/world.geo.json/master/countries.geo.json"), - // Bundle.main.url(forResource: "location", withExtension: "geojson"), - // guard let geoJsonFileUrl = URL(string: "https://hrbrmstr.github.io/noaa-alerts-sp-to-geojson/current-all.geojson"), - let geoJsonData = try? Data.init(contentsOf: geoJsonFileUrl) else { - fatalError("Failure to fetch the file.") - } - guard let objs = try? MKGeoJSONDecoder().decode(geoJsonData) as? [MKGeoJSONFeature] else { - fatalError("Wrong format") - } - // Parse the objects - objs.forEach { (feature) in - guard let geometry = feature.geometry.first, - let propData = feature.properties else { - return - } - // Check if it is MKPolygon - if let polygon = geometry as? MKPolygon { - let polygonInfo = try? JSONDecoder.init().decode(PolygonInfo.self, from: propData) - mapView.addOverlay(polygon) - // self.view?.render(overlay: polygon, info: polygonInfo) - } - // Check if it is MKPolyline - if let polyline = geometry as? MKPolyline { - mapView.addOverlay(polyline, level: .aboveLabels) - // let polylineInfo = try? JSONDecoder.init().decode(PolylineInfo.self, from: propData) - // self.view?.render(overlay: polyline, info: polylineInfo) - } - // Check if it is MKPointAnnotation - // if let annotation = geometry as? MKPointAnnotation { - // let info = try? JSONDecoder.init().decode(Info.self, from: propData) - // let storeAnnotation = StoreAnnotation.init(title: info?.name, - // subtitle: info?.subTitle, - // website: info?.website, - // coordinate: annotation.coordinate) - // self.view?.setAnnotations(annotations: [storeAnnotation]) - // } - } - } func makeUIView(context: Context) -> MKMapView { currentMapLayer = nil mapView.delegate = context.coordinator diff --git a/Meshtastic/Views/Nodes/Helpers/NodeMapSwiftUI.swift b/Meshtastic/Views/Nodes/Helpers/NodeMapSwiftUI.swift index 47bdc291..4dec706e 100644 --- a/Meshtastic/Views/Nodes/Helpers/NodeMapSwiftUI.swift +++ b/Meshtastic/Views/Nodes/Helpers/NodeMapSwiftUI.swift @@ -13,12 +13,13 @@ import WeatherKit @available(iOS 17.0, *) struct NodeMapSwiftUI: View { - @Namespace var mapScope @Environment(\.managedObjectContext) var context @EnvironmentObject var bleManager: BLEManager + /// Map State + @Namespace var mapScope @AppStorage("meshMapType") private var meshMapType = 0 @AppStorage("meshMapShowNodeHistory") private var showNodeHistory = false - @AppStorage("meshMapShowRouteLines") private var meshMapShowRouteLines = false + @AppStorage("meshMapShowRouteLines") private var showRouteLines = false @State private var selectedMapLayer: MapLayer = .standard @State var waypointCoordinate: WaypointCoordinate? @State var editingWaypoint: Int = 0 @@ -45,88 +46,84 @@ struct NodeMapSwiftUI: View { if mostRecent != nil { NavigationStack { ZStack { - Map(initialPosition: .camera(MapCamera(centerCoordinate: mostRecent!.coordinate, distance: 500, heading: 90, pitch: 60)), - bounds: MapCameraBounds(minimumDistance: 100, maximumDistance: 3500), + Map(initialPosition: .camera(MapCamera(centerCoordinate: mostRecent!.coordinate, distance: 1000, heading: 0, pitch: 60)), + bounds: MapCameraBounds(minimumDistance: 100, maximumDistance: .infinity), scope: mapScope) { /// Route Lines - if meshMapShowRouteLines { + if showRouteLines { MapPolyline(coordinates: lineCoords, contourStyle: .straight) - .stroke(Color(nodeColor.lighter()), lineWidth: 8) + .stroke(Color(nodeColor.lighter()), lineWidth: 6) } /// Node Annotations ForEach(positionArray.reversed(), id: \.id) { position in - Annotation(position.latest ? node.user?.shortName ?? "?" : "", coordinate: position.coordinate) { - ZStack { - - let pf = PositionFlags(rawValue: Int(position.nodePosition?.metadata?.positionFlags ?? 3)) - - let symbolName = "flipphone" - - if position.latest { - Circle() - .foregroundStyle(Color(nodeColor).opacity(0.4)) + let pf = PositionFlags(rawValue: Int(position.nodePosition?.metadata?.positionFlags ?? 3)) + let formatter = MeasurementFormatter() + let speedText = formatter.string(from: Measurement(value: Double(position.speed), unit: UnitSpeed.kilometersPerHour)) + Annotation(position.latest ? node.user?.shortName ?? "?" : (pf.contains(.Speed) && position.speed > 2) ? speedText : "", coordinate: position.coordinate) { + ZStack { + if position.latest { + Circle() + .foregroundStyle(Color(nodeColor.lighter()).opacity(0.4)) .frame(width: 60, height: 60) - - Image(systemName: symbolName) + + if pf.contains(.Heading) { + Image(systemName: pf.contains(.Speed) && position.speed > 1 ? "location.north.fill" : "hexagon") .symbolEffect(.pulse.byLayer) - .padding(7) - .foregroundStyle(Color(nodeColor.lighter()).isLight() ? .black : .white) + .padding(5) + .foregroundStyle(Color(nodeColor).isLight() ? .black : .white) .background(Color(UIColor(hex: UInt32(node.num)).darker())) .clipShape(Circle()) - .zIndex(100) + .rotationEffect(.degrees(Double(position.heading))) } else { - if showNodeHistory { - if pf.contains(.Heading) { -// if parent.userTrackingMode != MKUserTrackingMode.followWithHeading { -// annotationView.glyphImage = UIImage(systemName: "location.north.fill")? -// subtitle.text! += "Heading: \(String(positionAnnotation.heading)) \n" -// } else { -// annotationView.glyphImage = UIImage(systemName: "flipphone") -// } - } - if pf.contains(.Speed) { -// let formatter = MeasurementFormatter() -// formatter.locale = Locale.current -// if positionAnnotation.speed <= 1 { -// annotationView.glyphImage = UIImage(systemName: "hexagon") -// } -// subtitle.text! += "Speed: \(formatter.string(from: Measurement(value: Double(positionAnnotation.speed), unit: UnitSpeed.kilometersPerHour))) \n" - } - - + Image(systemName: "flipphone") + .symbolEffect(.pulse.byLayer) + .padding(5) + .foregroundStyle(Color(nodeColor).isLight() ? .black : .white) + .background(Color(UIColor(hex: UInt32(node.num)).darker())) + .clipShape(Circle()) + } + } else { + if showNodeHistory { + if pf.contains(.Heading) { + Image(systemName: pf.contains(.Speed) && position.speed > 0 ? "location.north.fill" : "hexagon") + .padding(2) + .foregroundStyle(Color(UIColor(hex: UInt32(node.num)).lighter()).isLight() ? .black : .white) + .background(Color(UIColor(hex: UInt32(node.num)).lighter())) + .clipShape(Circle()) + .rotationEffect(.degrees(Double(position.heading))) + } else { Image(systemName: "mappin.circle") .padding(2) .foregroundStyle(Color(UIColor(hex: UInt32(node.num)).lighter()).isLight() ? .black : .white) .background(Color(UIColor(hex: UInt32(node.num)).lighter())) .clipShape(Circle()) - .zIndex(1000) } } - } } - .tag(node.num) } + .tag(node.num) } - .mapScope(mapScope) - .mapStyle(.imagery(elevation: .realistic)) - .mapControls { - MapScaleView(scope: mapScope) - .mapControlVisibility(.visible) - MapUserLocationButton(scope: mapScope) - .mapControlVisibility(.visible) - MapPitchToggle(scope: mapScope) - .mapControlVisibility(.visible) - #if targetEnvironment(macCatalyst) - MapZoomStepper(scope: mapScope) - .mapControlVisibility(.visible) - MapPitchSlider(scope: mapScope) - .mapControlVisibility(.visible) - #endif - MapCompass(scope: mapScope) - .mapControlVisibility(.visible) - } - .controlSize(.regular) + } + .mapScope(mapScope) + .mapStyle(.imagery(elevation: .realistic)) + .mapControls { + MapScaleView(scope: mapScope) + .mapControlVisibility(.visible) + MapUserLocationButton(scope: mapScope) + .mapControlVisibility(.visible) + MapPitchToggle(scope: mapScope) + .mapControlVisibility(.visible) + #if targetEnvironment(macCatalyst) + MapZoomStepper(scope: mapScope) + .mapControlVisibility(.visible) + MapPitchSlider(scope: mapScope) + .mapControlVisibility(.visible) + #endif + MapCompass(scope: mapScope) + .mapControlVisibility(.visible) + } + .controlSize(.regular) } .navigationBarTitle(String("Node Map " + (node.user?.shortName ?? "unknown".localized)), displayMode: .inline) .navigationBarItems(trailing: