mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Mapkit for swiftui
This commit is contained in:
parent
6bd4a26a8b
commit
4014c80758
4 changed files with 122 additions and 13 deletions
|
|
@ -105,6 +105,7 @@
|
|||
DDB6ABE228B13FB500384BA1 /* PositionConfigEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABE128B13FB500384BA1 /* PositionConfigEnums.swift */; };
|
||||
DDB6ABE428B13FFF00384BA1 /* DisplayEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABE328B13FFF00384BA1 /* DisplayEnums.swift */; };
|
||||
DDB6ABE628B1406100384BA1 /* LoraConfigEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABE528B1406100384BA1 /* LoraConfigEnums.swift */; };
|
||||
DDB6CCFB2AAF805100945AF6 /* NodeMapSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6CCFA2AAF805100945AF6 /* NodeMapSwiftUI.swift */; };
|
||||
DDB75A0F2A05920E006ED576 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB75A0E2A05920E006ED576 /* FileManager.swift */; };
|
||||
DDB75A112A059258006ED576 /* Url.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB75A102A059258006ED576 /* Url.swift */; };
|
||||
DDB75A142A0593E2006ED576 /* OfflineTileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB75A132A0593E2006ED576 /* OfflineTileManager.swift */; };
|
||||
|
|
@ -313,6 +314,7 @@
|
|||
DDB6ABE128B13FB500384BA1 /* PositionConfigEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionConfigEnums.swift; sourceTree = "<group>"; };
|
||||
DDB6ABE328B13FFF00384BA1 /* DisplayEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayEnums.swift; sourceTree = "<group>"; };
|
||||
DDB6ABE528B1406100384BA1 /* LoraConfigEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoraConfigEnums.swift; sourceTree = "<group>"; };
|
||||
DDB6CCFA2AAF805100945AF6 /* NodeMapSwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeMapSwiftUI.swift; sourceTree = "<group>"; };
|
||||
DDB759E12A04B264006ED576 /* MeshtasticDataModelV12.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV12.xcdatamodel; sourceTree = "<group>"; };
|
||||
DDB75A0E2A05920E006ED576 /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = "<group>"; };
|
||||
DDB75A102A059258006ED576 /* Url.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Url.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -823,6 +825,7 @@
|
|||
DDDB26452AACC0B7003AFCB7 /* NodeInfoItem.swift */,
|
||||
DDDB26412AABF655003AFCB7 /* NodeListItem.swift */,
|
||||
DDDB26472AACD6D1003AFCB7 /* NodeMapControl.swift */,
|
||||
DDB6CCFA2AAF805100945AF6 /* NodeMapSwiftUI.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1181,6 +1184,7 @@
|
|||
DD994B69295F88B60013760A /* IntervalEnums.swift in Sources */,
|
||||
DD415828285859C4009B0E59 /* TelemetryConfig.swift in Sources */,
|
||||
DDDB443D29F6592F00EE2349 /* NetworkManager.swift in Sources */,
|
||||
DDB6CCFB2AAF805100945AF6 /* NodeMapSwiftUI.swift in Sources */,
|
||||
DD73FD1128750779000852D6 /* PositionLog.swift in Sources */,
|
||||
DD5E5206298EE33B00D21B61 /* localonly.pb.swift in Sources */,
|
||||
DD3CC6C028E7A60700FA9159 /* MessagingEnums.swift in Sources */,
|
||||
|
|
@ -1402,7 +1406,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Meshtastic/Meshtastic.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 655;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Meshtastic/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = GCH7VS5Y9R;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
|
|
@ -1436,7 +1440,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Meshtastic/Meshtastic.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 655;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Meshtastic/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = GCH7VS5Y9R;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,12 @@ struct NodeDetail: View {
|
|||
.disabled(!node.hasDeviceMetrics)
|
||||
Divider()
|
||||
NavigationLink {
|
||||
NodeMapControl(node: node)
|
||||
if #available (iOS 17, macOS 14, *) {
|
||||
NodeMapSwiftUI(node: node)
|
||||
} else {
|
||||
NodeMapControl(node: node)
|
||||
}
|
||||
|
||||
} label: {
|
||||
Image(systemName: "map")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
|
|
|
|||
110
Meshtastic/Views/Nodes/Helpers/NodeMapSwiftUI.swift
Normal file
110
Meshtastic/Views/Nodes/Helpers/NodeMapSwiftUI.swift
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
//
|
||||
// NodeMapSwiftUI.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 9/11/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import CoreLocation
|
||||
import MapKit
|
||||
import WeatherKit
|
||||
|
||||
@available(iOS 17.0, *)
|
||||
struct NodeMapSwiftUI: View {
|
||||
|
||||
@Namespace var mapScope
|
||||
@Environment(\.managedObjectContext) var context
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
@AppStorage("meshMapType") private var meshMapType = 0
|
||||
@AppStorage("meshMapShowNodeHistory") private var showNodeHistory = false
|
||||
@AppStorage("meshMapShowRouteLines") private var meshMapShowRouteLines = false
|
||||
@State private var selectedMapLayer: MapLayer = .standard
|
||||
@State var waypointCoordinate: WaypointCoordinate?
|
||||
@State var editingWaypoint: Int = 0
|
||||
@State private var customMapOverlay: MapViewSwiftUI.CustomMapOverlay? = MapViewSwiftUI.CustomMapOverlay(
|
||||
mapName: "offlinemap",
|
||||
tileType: "png",
|
||||
canReplaceMapContent: true
|
||||
)
|
||||
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "name", ascending: false)],
|
||||
predicate: NSPredicate(
|
||||
format: "expire == nil || expire >= %@", Date() as NSDate
|
||||
), animation: .none)
|
||||
private var waypoints: FetchedResults<WaypointEntity>
|
||||
@ObservedObject var node: NodeInfoEntity
|
||||
|
||||
var body: some View {
|
||||
let positionArray = node.positions?.array as? [PositionEntity] ?? []
|
||||
let mostRecent = node.positions?.lastObject as? PositionEntity
|
||||
if mostRecent != nil {
|
||||
NavigationStack {
|
||||
ZStack {
|
||||
|
||||
Map(initialPosition: .camera(MapCamera(centerCoordinate: mostRecent!.coordinate, distance: 500, heading: 90, pitch: 60)),
|
||||
bounds: MapCameraBounds(minimumDistance: 100, maximumDistance: 3500),
|
||||
scope: mapScope) {
|
||||
ForEach(positionArray, id: \.id) { position in
|
||||
Annotation(position.latest ? node.user?.shortName ?? "?" : "", coordinate: position.coordinate) {
|
||||
ZStack {
|
||||
if position.latest {
|
||||
Circle()
|
||||
.foregroundStyle(Color(UIColor(hex: UInt32(node.num)).darker()).opacity(0.4))
|
||||
.frame(width: 60, height: 60)
|
||||
Image(systemName: "flipphone")
|
||||
.symbolEffect(.pulse.byLayer)
|
||||
.padding(7)
|
||||
.foregroundStyle(Color(UIColor(hex: UInt32(node.num)).lighter()).isLight() ? .black : .white)
|
||||
.background(Color(UIColor(hex: UInt32(node.num)).darker()))
|
||||
.clipShape(Circle())
|
||||
} else {
|
||||
if showNodeHistory {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.tag(node.num)
|
||||
|
||||
// Marker(node.user?.shortName ?? "?", systemImage: "mappin.and.ellipse", coordinate: position.coordinate)
|
||||
// .tint(position.latest ? Color(UIColor(hex: UInt32(node.num)).darker()) : Color(UIColor(hex: UInt32(node.num)).lighter()))
|
||||
// .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(.large)
|
||||
}
|
||||
.navigationBarTitle(String("Node Map " + (node.user?.shortName ?? "unknown".localized)), displayMode: .inline)
|
||||
.navigationBarItems(trailing:
|
||||
ZStack {
|
||||
ConnectedDevice(
|
||||
bluetoothOn: bleManager.isSwitchedOn,
|
||||
deviceConnected: bleManager.connectedPeripheral != nil,
|
||||
name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?")
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,16 +7,6 @@
|
|||
import SwiftUI
|
||||
import CoreLocation
|
||||
|
||||
enum SelectedDetail {
|
||||
case positionLog
|
||||
case nodeMap
|
||||
case deviceMetricsLog
|
||||
case environmentMetricsLog
|
||||
case detectionSensorLog
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct NodeList: View {
|
||||
|
||||
@State private var columnVisibility = NavigationSplitViewVisibility.all
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue