Remove tracking mode setting, add button to mesh map

This commit is contained in:
Garth Vander Houwen 2023-04-23 22:38:02 -07:00
parent b367fde3db
commit 7e080cb2c6
8 changed files with 121 additions and 61 deletions

View file

@ -117,6 +117,7 @@
DDD6EEAF29BC024700383354 /* Firmware.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD6EEAE29BC024700383354 /* Firmware.swift */; };
DDD94A502845C8F5004A87A0 /* DateTimeText.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD94A4F2845C8F5004A87A0 /* DateTimeText.swift */; };
DDD9E4E4284B208E003777C5 /* UserEntityExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD9E4E3284B208E003777C5 /* UserEntityExtension.swift */; };
DDDB443629F6287000EE2349 /* MapButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDB443529F6287000EE2349 /* MapButtons.swift */; };
DDDE59F529AF163D00490C6C /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD41A61C29AE7E8E003C5A37 /* WidgetKit.framework */; };
DDDE59F629AF163D00490C6C /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD41A61E29AE7E8F003C5A37 /* SwiftUI.framework */; };
DDDE59F929AF163D00490C6C /* WidgetsBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDE59F829AF163D00490C6C /* WidgetsBundle.swift */; };
@ -297,6 +298,7 @@
DDD6EEAE29BC024700383354 /* Firmware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Firmware.swift; sourceTree = "<group>"; };
DDD94A4F2845C8F5004A87A0 /* DateTimeText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTimeText.swift; sourceTree = "<group>"; };
DDD9E4E3284B208E003777C5 /* UserEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserEntityExtension.swift; sourceTree = "<group>"; };
DDDB443529F6287000EE2349 /* MapButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapButtons.swift; sourceTree = "<group>"; };
DDDD527729B5B83F0045BC3C /* MeshtasticDataModelV9.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV9.xcdatamodel; sourceTree = "<group>"; };
DDDE59F429AF163D00490C6C /* WidgetsExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetsExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
DDDE59F829AF163D00490C6C /* WidgetsBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetsBundle.swift; sourceTree = "<group>"; };
@ -365,6 +367,7 @@
C9697F9C279336B700250207 /* LocalMBTileOverlay.swift */,
DD964FC32974767D007C176F /* MapViewFitExtension.swift */,
DD2AD8A7296D2DF9001FF0E7 /* MapViewSwiftUI.swift */,
DDDB443529F6287000EE2349 /* MapButtons.swift */,
);
path = Custom;
sourceTree = "<group>";
@ -904,6 +907,7 @@
DD5E523F298F5A9E00D21B61 /* AirQualityIndexCompact.swift in Sources */,
DD964FBF296E76EF007C176F /* WaypointFormView.swift in Sources */,
DD3501892852FC3B000FC853 /* Settings.swift in Sources */,
DDDB443629F6287000EE2349 /* MapButtons.swift in Sources */,
DD5D0A9C2931B9F200F7EA61 /* EthernetModes.swift in Sources */,
DD5E5203298EE33B00D21B61 /* config.pb.swift in Sources */,
DD798B072915928D005217CD /* ChannelMessageList.swift in Sources */,

View file

@ -97,6 +97,13 @@ enum UserTrackingModes: Int, CaseIterable, Identifiable {
return NSLocalizedString("map.usertrackingmode.followwithheading", comment: "Follow with Heading")
}
}
var icon: String {
switch self {
case .none: return "location"
case .follow: return "location.fill"
case .followWithHeading: return "location.north.line.fill"
}
}
func MKUserTrackingModeValue() -> MKUserTrackingMode {
switch self {

View file

@ -193,7 +193,6 @@ extension UserDefaults {
case meshMapCenteringMode
case meshMapRecentering
case meshMapCustomTileServer
case meshMapUserTrackingMode
case meshMapShowNodeHistory
case meshMapShowRouteLines
}

View file

@ -61,12 +61,6 @@ class UserSettings: ObservableObject {
UserDefaults.standard.synchronize()
}
}
@Published var meshMapUserTrackingMode: Int {
didSet {
UserDefaults.standard.set(meshMapUserTrackingMode, forKey: "meshMapUserTrackingMode")
UserDefaults.standard.synchronize()
}
}
@Published var meshMapShowNodeHistory: Bool {
didSet {
UserDefaults.standard.set(meshMapShowNodeHistory, forKey: "meshMapShowNodeHistory")
@ -91,7 +85,6 @@ class UserSettings: ObservableObject {
self.meshMapCenteringMode = UserDefaults.standard.object(forKey: "meshMapCenteringMode") as? Int ?? 0
self.meshMapRecentering = UserDefaults.standard.object(forKey: "meshMapRecentering") as? Bool ?? false
self.meshMapCustomTileServer = UserDefaults.standard.string(forKey: "meshMapCustomTileServer") ?? ""
self.meshMapUserTrackingMode = UserDefaults.standard.object(forKey: "meshMapUserTrackingMode") as? Int ?? 0
self.meshMapShowNodeHistory = UserDefaults.standard.object(forKey: "meshMapShowNodeHistory") as? Bool ?? true
self.meshMapShowRouteLines = UserDefaults.standard.object(forKey: "meshMapShowRouteLines") as? Bool ?? false
}

View file

@ -0,0 +1,66 @@
//
// MapButtons.swift
// Meshtastic
//
// Copyright © Garth Vander Houwen 4/23/23.
//
import SwiftUI
struct MapButtons: View {
let buttonWidth: CGFloat = 22
let width: CGFloat = 45
@Binding var tracking: UserTrackingModes
@Binding var isPresentingInfoSheet: Bool
var body: some View {
VStack() {
let impactLight = UIImpactFeedbackGenerator(style: .light)
Button(action: {
self.isPresentingInfoSheet.toggle()
}) {
Image(systemName: isPresentingInfoSheet ? "info.circle.fill" : "info.circle")
.resizable()
.frame(width: buttonWidth, height: buttonWidth, alignment: .center)
.offset(y: -2)
}
Divider()
Button(action: {
switch self.tracking {
case .none:
self.tracking = .follow
case .follow:
self.tracking = .followWithHeading
case .followWithHeading:
self.tracking = .none
}
impactLight.impactOccurred()
}) {
Image(systemName: tracking.icon)
.frame(width: buttonWidth, height: buttonWidth, alignment: .center)
.offset(y: 3)
}
}
.frame(width: width, height: width*2, alignment: .center)
.background(Color(UIColor.systemBackground))
.cornerRadius(8)
.shadow(radius: 1)
.offset(y: 25)
}
}
// MARK: Previews
struct MapControl_Previews: PreviewProvider {
@State static var tracking: UserTrackingModes = .none
@State static var isPresentingInfoSheet = false
static var previews: some View {
Group {
MapButtons(tracking: $tracking, isPresentingInfoSheet: $isPresentingInfoSheet)
.environment(\.colorScheme, .light)
MapButtons(tracking: $tracking, isPresentingInfoSheet: $isPresentingInfoSheet)
.environment(\.colorScheme, .dark)
}
.previewLayout(.fixed(width: 60, height: 100))
}
}

View file

@ -29,7 +29,6 @@ struct MapViewSwiftUI: UIViewRepresentable {
@State private var loadedLastUpdatedLocalMapFile = 0
var customMapOverlay: CustomMapOverlay?
@State private var presentCustomMapOverlayHash: CustomMapOverlay?
// Custom Tile Server
@AppStorage("meshMapCustomTileServer") private var tileServerUrl = ""
var tileRenderer: MKTileOverlayRenderer?
@ -70,10 +69,6 @@ struct MapViewSwiftUI: UIViewRepresentable {
mapView.showsScale = true
mapView.showsTraffic = true
let overlay = TileServerOverlay() // Offline-Map-Tiles
overlay.canReplaceMapContent = true
mapView.addOverlay(overlay, level: .aboveLabels)
#if targetEnvironment(macCatalyst)
// Show the default always visible compass and the mac only controls
mapView.showsCompass = true
@ -99,10 +94,29 @@ struct MapViewSwiftUI: UIViewRepresentable {
func updateUIView(_ mapView: MKMapView, context: Context) {
mapView.mapType = mapViewType
if self.customMapOverlay != self.presentCustomMapOverlayHash || self.loadedLastUpdatedLocalMapFile != self.lastUpdatedLocalMapFile {
if tileServerUrl.count > 0 {
tileRenderer?.alpha = 0.0
let overlays = mapView.overlays
if mapView.mapType == .standard {
let overlay = MKTileOverlay(urlTemplate: tileServerUrl)
if overlays.contains(where: {$0 is MKPolyline}) {
mapView.addOverlay(overlay, level: .aboveLabels)
if let poly_overlay = overlays.filter({$0 is MKPolyline}).first {
mapView.addOverlay(poly_overlay, level: .aboveLabels)
}
} else {
mapView.addOverlay(overlay, level: .aboveLabels)
}
} else {
for overlay in overlays {
if let ove = overlay as? MKTileOverlay {
mapView.removeOverlay(ove)
}
}
}
} else if self.customMapOverlay != self.presentCustomMapOverlayHash || self.loadedLastUpdatedLocalMapFile != self.lastUpdatedLocalMapFile {
mapView.removeOverlays(mapView.overlays)
if self.customMapOverlay != nil {
@ -131,7 +145,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
.sorted { $0.nodePosition?.num ?? 0 > $1.nodePosition?.num ?? -1 }
let annotationCount = waypoints.count + (showNodeHistory ? positions.count : latest.count)
if annotationCount != mapView.annotations.count {
// if annotationCount != mapView.annotations.count {
print("Annotation Count: \(annotationCount) Map Annotations: \(mapView.annotations.count)")
mapView.removeAnnotations(mapView.annotations)
mapView.addAnnotations(waypoints)
@ -152,7 +166,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
})
let polyline = MKPolyline(coordinates: lineCoords, count: nodePositions.count)
polyline.title = "\(String(position.nodePosition?.num ?? 0))"
mapView.addOverlay(polyline)
mapView.addOverlay(polyline, level: .aboveLabels)
lineIndex += 1
// There are 18 colors for lines, start over if we are at index 17
if lineIndex > 17 {
@ -176,30 +190,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
mapView.showsUserLocation = true
}
mapView.setUserTrackingMode(userTrackingMode, animated: true)
if tileServerUrl.count > 0 {
tileRenderer?.alpha = 0.0
let overlays = mapView.overlays
if mapView.mapType == .standard {
let overlay = MKTileOverlay(urlTemplate: tileServerUrl)
if overlays.contains(where: {$0 is MKPolyline}) {
mapView.addOverlay(overlay, level: .aboveLabels)
if let poly_overlay = overlays.filter({$0 is MKPolyline}).first {
mapView.addOverlay(poly_overlay, level: .aboveRoads)
}
} else {
mapView.addOverlay(overlay, level: .aboveRoads)
}
} else {
for overlay in overlays {
if let ove = overlay as? MKTileOverlay {
mapView.removeOverlay(ove)
}
}
}
}
}
//}
}
}

View file

@ -17,7 +17,6 @@ struct NodeMap: View {
@EnvironmentObject var userSettings: UserSettings
@AppStorage("meshMapType") private var meshMapType = "hybridFlyover"
@AppStorage("meshMapUserTrackingMode") private var meshMapUserTrackingMode = 0
@AppStorage("meshMapShowNodeHistory") private var meshMapShowNodeHistory = false
@AppStorage("meshMapShowRouteLines") private var meshMapShowRouteLines = false
@ -32,7 +31,9 @@ struct NodeMap: View {
private var waypoints: FetchedResults<WaypointEntity>
@State private var mapType: MKMapType = .standard
@State private var userTrackingMode: MKUserTrackingMode = .none
@State var selectedTracking: UserTrackingModes = .none
@State var isPresentingInfoSheet: Bool = false
@State var waypointCoordinate: WaypointCoordinate?
@State private var customMapOverlay: MapViewSwiftUI.CustomMapOverlay? = MapViewSwiftUI.CustomMapOverlay(
mapName: "offlinemap",
@ -56,11 +57,23 @@ struct NodeMap: View {
positions: Array(positions),
waypoints: Array(waypoints),
mapViewType: mapType,
userTrackingMode: userTrackingMode,
userTrackingMode: selectedTracking.MKUserTrackingModeValue(),
showNodeHistory: meshMapShowNodeHistory,
showRouteLines: meshMapShowRouteLines,
customMapOverlay: self.customMapOverlay
)
VStack(alignment: .trailing) {
HStack(alignment: .top) {
Spacer()
MapButtons(tracking: $selectedTracking, isPresentingInfoSheet: $isPresentingInfoSheet)
.padding(.trailing, 8)
.padding(.top, 16)
}
Spacer()
}
VStack {
Spacer()
Picker("Map Type", selection: $mapType) {
@ -94,7 +107,6 @@ struct NodeMap: View {
UIApplication.shared.isIdleTimerDisabled = true
self.bleManager.context = context
self.bleManager.userSettings = userSettings
userTrackingMode = UserTrackingModes(rawValue: meshMapUserTrackingMode)?.MKUserTrackingModeValue() ?? MKUserTrackingMode.none
switch meshMapType {
case "standard":
mapType = .standard

View file

@ -82,15 +82,6 @@ struct AppSettings: View {
.font(.caption)
.foregroundColor(.gray)
}
Picker("map.usertrackingmode", selection: $userSettings.meshMapUserTrackingMode) {
ForEach(UserTrackingModes.allCases) { utm in
Text(utm.description)
}
}
.pickerStyle(DefaultPickerStyle())
Text("When follow or follow with heading are selected maps will automatically center on the location of the GPS on the connected phone.")
.font(.caption)
.foregroundColor(.gray)
}
Section(header: Text("map options")) {
@ -102,14 +93,11 @@ struct AppSettings: View {
}
.pickerStyle(DefaultPickerStyle())
if userSettings.meshMapUserTrackingMode == 0 {
Toggle(isOn: $userSettings.meshMapRecentering) {
Toggle(isOn: $userSettings.meshMapRecentering) {
Label("map.recentering", systemImage: "camera.metering.center.weighted")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Label("map.recentering", systemImage: "camera.metering.center.weighted")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Toggle(isOn: $userSettings.meshMapShowNodeHistory) {
Label("Show Node History", systemImage: "building.columns.fill")