mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Clean up map type code
Add custom tile server url to app settings
This commit is contained in:
parent
1ea7897c1e
commit
ea0342d0e9
7 changed files with 104 additions and 48 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue