Clean up map type code

Add custom tile server url to app settings
This commit is contained in:
Garth Vander Houwen 2023-04-10 19:14:54 -07:00
parent 1ea7897c1e
commit ea0342d0e9
7 changed files with 104 additions and 48 deletions

View file

@ -9,13 +9,13 @@ import Foundation
import MapKit
enum KeyboardType: Int, CaseIterable, Identifiable {
case defaultKeyboard = 0
case asciiCapable = 1
case twitter = 9
case emailAddress = 7
case numbersAndPunctuation = 2
var id: Int { self.rawValue }
var description: String {
switch self {
@ -34,16 +34,16 @@ enum KeyboardType: Int, CaseIterable, Identifiable {
}
enum MeshMapType: String, CaseIterable, Identifiable {
case standard
case mutedStandard
case hybrid
case hybridFlyover
case satellite
case satelliteFlyover
var id: String { self.rawValue }
var description: String {
switch self {
case .standard:
@ -61,7 +61,7 @@ enum MeshMapType: String, CaseIterable, Identifiable {
}
}
func MKMapTypeValue() -> MKMapType {
switch self {
case .standard:
return MKMapType.standard
@ -80,13 +80,13 @@ enum MeshMapType: String, CaseIterable, Identifiable {
}
enum UserTrackingModes: Int, CaseIterable, Identifiable {
case none = 0
case follow = 1
case followWithHeading = 2
var id: Int { self.rawValue }
var description: String {
switch self {
case .none:
@ -98,7 +98,7 @@ enum UserTrackingModes: Int, CaseIterable, Identifiable {
}
}
func MKUserTrackingModeValue() -> MKUserTrackingMode {
switch self {
case .none:
return MKUserTrackingMode.none
@ -111,7 +111,7 @@ enum UserTrackingModes: Int, CaseIterable, Identifiable {
}
enum LocationUpdateInterval: Int, CaseIterable, Identifiable {
case fiveSeconds = 5
case tenSeconds = 10
case fifteenSeconds = 15
@ -120,7 +120,7 @@ enum LocationUpdateInterval: Int, CaseIterable, Identifiable {
case fiveMinutes = 300
case tenMinutes = 600
case fifteenMinutes = 900
var id: Int { self.rawValue }
var description: String {
switch self {
@ -143,3 +143,30 @@ enum LocationUpdateInterval: Int, CaseIterable, Identifiable {
}
}
}
enum MapTileServerLinks: Int, CaseIterable, Identifiable {
case openStreetMaps
case wikimedia
case nationalMap
var id: Int { self.rawValue }
var tileUrl: String {
switch self {
case .wikimedia:
return "https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png"
case .openStreetMaps:
return "https://tile.openstreetmap.org/{z}/{x}/{y}.png"
case .nationalMap:
return "https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}"
}
}
var zoomRange: [Int] {
switch self {
case .wikimedia:
return [Int](0...24)
case .openStreetMaps:
return [Int](0...24)
case .nationalMap:
return [Int](0...24)
}
}
}

View file

@ -827,7 +827,7 @@ func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) {
waypoint.longitudeI = waypointMessage.longitudeI
waypoint.icon = Int64(waypointMessage.icon)
waypoint.locked = Int64(waypointMessage.lockedTo)
if waypointMessage.expire > 0 {
if waypointMessage.expire >= 1 {
waypoint.expire = Date(timeIntervalSince1970: TimeInterval(Int64(waypointMessage.expire)))
} else {
waypoint.expire = nil
@ -849,7 +849,7 @@ func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) {
fetchedWaypoint[0].longitudeI = waypointMessage.longitudeI
fetchedWaypoint[0].icon = Int64(waypointMessage.icon)
fetchedWaypoint[0].locked = Int64(waypointMessage.lockedTo)
if waypointMessage.expire > 1 {
if waypointMessage.expire >= 1 {
fetchedWaypoint[0].expire = Date(timeIntervalSince1970: TimeInterval(Int64(waypointMessage.expire)))
} else {
fetchedWaypoint[0].expire = nil

View file

@ -11,6 +11,7 @@ class UserSettings: ObservableObject {
@Published var meshtasticUsername: String {
didSet {
UserDefaults.standard.set(meshtasticUsername, forKey: "meshtasticusername")
UserDefaults.standard.synchronize()
}
}
@Published var preferredPeripheralId: String {
@ -27,16 +28,19 @@ class UserSettings: ObservableObject {
@Published var provideLocationInterval: Int {
didSet {
UserDefaults.standard.set(provideLocationInterval, forKey: "provideLocationInterval")
UserDefaults.standard.synchronize()
}
}
@Published var keyboardType: Int {
didSet {
UserDefaults.standard.set(keyboardType, forKey: "keyboardType")
UserDefaults.standard.synchronize()
}
}
@Published var meshMapType: String {
didSet {
UserDefaults.standard.set(meshMapType, forKey: "meshMapType")
UserDefaults.standard.synchronize()
}
}
@Published var meshMapCenteringMode: Int {
@ -54,6 +58,7 @@ class UserSettings: ObservableObject {
@Published var meshMapCustomTileServer: String {
didSet {
UserDefaults.standard.set(meshMapCustomTileServer, forKey: "meshMapCustomTileServer")
UserDefaults.standard.synchronize()
}
}
@Published var meshMapUserTrackingMode: Int {

View file

@ -31,6 +31,11 @@ struct MapViewSwiftUI: UIViewRepresentable {
var customMapOverlay: CustomMapOverlay?
@State private var presentCustomMapOverlayHash: CustomMapOverlay?
// Custom Tile Server
@AppStorage("meshMapCustomTileServer") private var tileServerUrl = ""
var tileRenderer: MKTileOverlayRenderer?
let tileServer: MapTileServerLinks = .openStreetMaps
func makeUIView(context: Context) -> MKMapView {
// Map View Parameters
mapView.mapType = mapViewType
@ -85,6 +90,10 @@ struct MapViewSwiftUI: UIViewRepresentable {
#endif
#endif
if tileServerUrl.count > 0 {
context.coordinator.setupTileServerRenderer()
}
mapView.delegate = context.coordinator
return mapView
}
@ -162,6 +171,29 @@ 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: .aboveLabels)
}
} else {
mapView.addOverlay(overlay, level: .aboveLabels)
}
} else {
for overlay in overlays {
if let ove = overlay as? MKTileOverlay {
mapView.removeOverlay(ove)
}
}
}
}
}
func makeCoordinator() -> MapCoordinator {
@ -352,6 +384,14 @@ struct MapViewSwiftUI: UIViewRepresentable {
return MKOverlayRenderer()
}
}
func setupTileServerRenderer() {
//let template = "https://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}.jpg"
//let template = "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.jpg"
let overlay = MKTileOverlay(urlTemplate: parent.tileServerUrl)
parent.mapView.addOverlay(overlay, level: .aboveLabels)
parent.tileRenderer = MKTileOverlayRenderer(tileOverlay: overlay)
}
}
/// is supposed to be located in the folder with the map name

View file

@ -217,22 +217,8 @@ struct NodeDetail: View {
})
.onAppear {
self.bleManager.context = context
switch meshMapType {
case "standard":
mapType = .standard
case "mutedStandard":
mapType = .mutedStandard
case "hybrid":
mapType = .hybrid
case "hybridFlyover":
mapType = .hybridFlyover
case "satellite":
mapType = .satellite
case "satelliteFlyover":
mapType = .satelliteFlyover
default:
mapType = .hybridFlyover
}
let currentMapType = MeshMapType(rawValue: meshMapType)
mapType = currentMapType?.MKMapTypeValue() ?? .standard
}
.task(id: node.num) {
if !loadedWeather {

View file

@ -37,7 +37,7 @@ struct NodeMap: View {
}
}
}
@AppStorage("meshMapType") private var meshMapType = "hybridFlyover"
@AppStorage("meshMapType") private var meshMapType = "standard"
@AppStorage("meshMapUserTrackingMode") private var meshMapUserTrackingMode = 0
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "time", ascending: true)],
@ -111,22 +111,8 @@ struct NodeMap: View {
self.bleManager.context = context
self.bleManager.userSettings = userSettings
userTrackingMode = UserTrackingModes(rawValue: meshMapUserTrackingMode)?.MKUserTrackingModeValue() ?? MKUserTrackingMode.none
switch meshMapType {
case "standard":
mapType = .standard
case "mutedStandard":
mapType = .mutedStandard
case "hybrid":
mapType = .hybrid
case "hybridFlyover":
mapType = .hybridFlyover
case "satellite":
mapType = .satellite
case "satelliteFlyover":
mapType = .satelliteFlyover
default:
mapType = .hybridFlyover
}
let currentMapType = MeshMapType(rawValue: meshMapType)
mapType = currentMapType?.MKMapTypeValue() ?? .standard
})
.onDisappear(perform: {
UIApplication.shared.isIdleTimerDisabled = false

View file

@ -26,7 +26,6 @@ struct AppSettings: View {
}
.keyboardType(.asciiCapable)
.disableAutocorrection(true)
.listRowSeparator(.visible)
}
Section(header: Text("options")) {
@ -120,6 +119,19 @@ struct AppSettings: View {
Label("Show Route Lines", systemImage: "road.lanes")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
HStack {
Label("Tile Server", systemImage: "square.grid.3x2")
TextField(
"Tile Server",
text: $userSettings.meshMapCustomTileServer,
axis: .vertical
)
.foregroundColor(.gray)
}
.keyboardType(.asciiCapable)
.disableAutocorrection(true)
}
}
HStack {