mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Node distance filter for the mesh map
This commit is contained in:
parent
5c212cff04
commit
554fe9a3ca
9 changed files with 83 additions and 11 deletions
|
|
@ -50,6 +50,20 @@ enum MeshMapTypes: Int, CaseIterable, Identifiable {
|
|||
}
|
||||
}
|
||||
|
||||
enum MeshMapDistances: Double, CaseIterable, Identifiable {
|
||||
case fiftyMiles = 80467.2
|
||||
case oneHundredMiles = 160934
|
||||
case twoHundredMiles = 321869
|
||||
case fiveHundredMiles = 804672
|
||||
case oneThousandMiles = 1609000
|
||||
case twoThousandMiles = 3218688
|
||||
var id: Double { self.rawValue }
|
||||
var description: String {
|
||||
let distanceFormatter = MKDistanceFormatter()
|
||||
return "\(distanceFormatter.string(fromDistance: Double(self.rawValue))) away"
|
||||
}
|
||||
}
|
||||
|
||||
enum UserTrackingModes: Int, CaseIterable, Identifiable {
|
||||
case none = 0
|
||||
case follow = 1
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ extension PositionEntity {
|
|||
request.returnsDistinctResults = true
|
||||
request.sortDescriptors = [NSSortDescriptor(key: "time", ascending: false)]
|
||||
|
||||
let positionPredicate = NSPredicate(format: "nodePosition != nil && nodePosition.user.shortName != nil && latest == true && time >= %@", Calendar.current.date(byAdding: .day, value: -2, to: Date())! as NSDate)
|
||||
let positionPredicate = NSPredicate(format: "nodePosition != nil && (nodePosition.user.shortName != nil || nodePosition.user.shortName != '') && latest == true && time >= %@", Calendar.current.date(byAdding: .day, value: -2, to: Date())! as NSDate)
|
||||
|
||||
let pointOfInterest = LocationHelper.currentLocation
|
||||
|
||||
if pointOfInterest.latitude != LocationHelper.DefaultLocation.latitude && pointOfInterest.longitude != LocationHelper.DefaultLocation.longitude {
|
||||
/// Lets just get nodes within about 500 miles
|
||||
let D: Double = 800000 * 1.1
|
||||
let D: Double = UserDefaults.meshMapDistance * 1.1
|
||||
let R: Double = 6371009
|
||||
let meanLatitidue = pointOfInterest.latitude * .pi / 180
|
||||
let deltaLatitude = D / R * 180 / .pi
|
||||
|
|
|
|||
|
|
@ -67,4 +67,29 @@ extension String {
|
|||
: $0 + String($1)
|
||||
}
|
||||
}
|
||||
|
||||
var length: Int {
|
||||
return count
|
||||
}
|
||||
|
||||
subscript (i: Int) -> String {
|
||||
return self[i ..< i + 1]
|
||||
}
|
||||
|
||||
func substring(fromIndex: Int) -> String {
|
||||
return self[min(fromIndex, length) ..< length]
|
||||
}
|
||||
|
||||
func substring(toIndex: Int) -> String {
|
||||
return self[0 ..< max(0, toIndex)]
|
||||
}
|
||||
|
||||
subscript (r: Range<Int>) -> String {
|
||||
let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
|
||||
upper: min(length, max(0, r.upperBound))))
|
||||
let start = index(startIndex, offsetBy: range.lowerBound)
|
||||
let end = index(start, offsetBy: range.upperBound - range.lowerBound)
|
||||
return String(self[start ..< end])
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ extension UserDefaults {
|
|||
case provideLocation
|
||||
case provideLocationInterval
|
||||
case mapLayer
|
||||
case meshMapDistance
|
||||
case meshMapRecentering
|
||||
case meshMapShowNodeHistory
|
||||
case meshMapShowRouteLines
|
||||
|
|
@ -76,6 +77,9 @@ extension UserDefaults {
|
|||
@UserDefault(.mapLayer, defaultValue: .standard)
|
||||
static var mapLayer: MapLayer
|
||||
|
||||
@UserDefault(.meshMapDistance, defaultValue: 800000)
|
||||
static var meshMapDistance: Double
|
||||
|
||||
@UserDefault(.enableMapRecentering, defaultValue: false)
|
||||
static var enableMapRecentering: Bool
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import ActivityKit
|
|||
func generateMessageMarkdown (message: String) -> String {
|
||||
let types: NSTextCheckingResult.CheckingType = [.address, .link, .phoneNumber]
|
||||
let detector = try! NSDataDetector(types: types.rawValue)
|
||||
let matches = detector.matches(in: message, options: [], range: NSRange(location: 0, length: message.utf16.count))
|
||||
let matches = detector.matches(in: message, options: [], range: NSRange(location: 0, length: message.utf8.count))
|
||||
var messageWithMarkdown = message
|
||||
if matches.count > 0 {
|
||||
for match in matches {
|
||||
|
|
@ -28,9 +28,14 @@ func generateMessageMarkdown (message: String) -> String {
|
|||
let phone = messageWithMarkdown[range]
|
||||
messageWithMarkdown = messageWithMarkdown.replacingOccurrences(of: phone, with: "[\(phone)](tel:\(phone))")
|
||||
} else if match.resultType == .link {
|
||||
let url = messageWithMarkdown[range]
|
||||
let absoluteUrl = match.url?.absoluteString ?? ""
|
||||
messageWithMarkdown = messageWithMarkdown.replacingOccurrences(of: url, with: "[\(String(match.url?.host ?? "Link"))\(String(match.url?.path ?? ""))](\(absoluteUrl))")
|
||||
let start = match.range.lowerBound
|
||||
let stop = match.range.upperBound
|
||||
if stop > start {
|
||||
let url = message[start ..< stop]
|
||||
let absoluteUrl = match.url?.absoluteString ?? ""
|
||||
let markdownUrl = "[\(url)](\(absoluteUrl))"
|
||||
messageWithMarkdown = messageWithMarkdown.replacingOccurrences(of: url, with: markdownUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ struct MapSettingsForm: View {
|
|||
@Binding var traffic: Bool
|
||||
@Binding var pointsOfInterest: Bool
|
||||
@Binding var mapLayer: MapLayer
|
||||
@Binding var meshMapDistance: Double
|
||||
@Binding var meshMap: Bool
|
||||
|
||||
var body: some View {
|
||||
|
|
@ -56,6 +57,27 @@ struct MapSettingsForm: View {
|
|||
self.routeLines.toggle()
|
||||
UserDefaults.enableMapRouteLines = self.routeLines
|
||||
}
|
||||
} else {
|
||||
VStack {
|
||||
HStack {
|
||||
Label("Show nodes up to", systemImage: "lines.measurement.horizontal")
|
||||
Picker("", selection: $meshMapDistance) {
|
||||
ForEach(MeshMapDistances.allCases) { di in
|
||||
Text(di.description)
|
||||
.tag(di.id)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
}
|
||||
.listRowSeparator(.hidden)
|
||||
Text("You will need to close and re-open the app for this to take effect.")
|
||||
.font(.callout)
|
||||
.foregroundColor(.gray)
|
||||
.listRowSeparator(/*@START_MENU_TOKEN@*/.visible/*@END_MENU_TOKEN@*/)
|
||||
}
|
||||
.onChange(of: meshMapDistance) { newMeshMapDistance in
|
||||
UserDefaults.meshMapDistance = newMeshMapDistance
|
||||
}
|
||||
}
|
||||
Toggle(isOn: $convexHull) {
|
||||
Label("Convex Hull", systemImage: "button.angledbottom.horizontal.right")
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ struct NodeMapSwiftUI: View {
|
|||
@State var showUserLocation: Bool = false
|
||||
@State var positions: [PositionEntity] = []
|
||||
/// Map State User Defaults
|
||||
@AppStorage("meshMapDistance") private var meshMapDistance: Double = 800000
|
||||
@AppStorage("meshMapShowNodeHistory") private var showNodeHistory = false
|
||||
@AppStorage("meshMapShowRouteLines") private var showRouteLines = false
|
||||
@AppStorage("enableMapConvexHull") private var showConvexHull = false
|
||||
|
|
@ -92,7 +93,7 @@ struct NodeMapSwiftUI: View {
|
|||
.padding()
|
||||
}
|
||||
.sheet(isPresented: $isEditingSettings) {
|
||||
MapSettingsForm(nodeHistory: $showNodeHistory, routeLines: $showRouteLines, convexHull: $showConvexHull, traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMap: $isMeshMap)
|
||||
MapSettingsForm(nodeHistory: $showNodeHistory, routeLines: $showRouteLines, convexHull: $showConvexHull, traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMapDistance: $meshMapDistance, meshMap: $isMeshMap)
|
||||
.onChange(of: (selectedMapLayer)) { newMapLayer in
|
||||
switch selectedMapLayer {
|
||||
case .standard:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ struct MeshMap: View {
|
|||
/// Parameters
|
||||
@State var showUserLocation: Bool = true
|
||||
/// Map State User Defaults
|
||||
@AppStorage("meshMapDistance") private var meshMapDistance: Double = 800000
|
||||
@AppStorage("meshMapShowNodeHistory") private var showNodeHistory = false
|
||||
@AppStorage("meshMapShowRouteLines") private var showRouteLines = false
|
||||
@AppStorage("enableMapConvexHull") private var showConvexHull = false
|
||||
|
|
@ -32,8 +33,8 @@ struct MeshMap: View {
|
|||
@AppStorage("mapLayer") private var selectedMapLayer: MapLayer = .standard
|
||||
// Map Configuration
|
||||
@Namespace var mapScope
|
||||
@State var mapStyle: MapStyle = MapStyle.standard(elevation: .flat, emphasis: MapStyle.StandardEmphasis.muted ,pointsOfInterest: .all, showsTraffic: true)
|
||||
@State var position = MapCameraPosition.camera(MapCamera(centerCoordinate: LocationHelper.currentLocation, distance: 2500000, heading: 0, pitch: 0))
|
||||
@State var mapStyle: MapStyle = MapStyle.standard(elevation: .flat, emphasis: MapStyle.StandardEmphasis.muted ,pointsOfInterest: .excludingAll, showsTraffic: false)
|
||||
@State var position = MapCameraPosition.automatic
|
||||
@State var isEditingSettings = false
|
||||
@State var selectedPosition: PositionEntity?
|
||||
@State var showWaypoints = false
|
||||
|
|
@ -120,7 +121,7 @@ struct MeshMap: View {
|
|||
.padding()
|
||||
}
|
||||
.sheet(isPresented: $isEditingSettings) {
|
||||
MapSettingsForm(nodeHistory: $showNodeHistory, routeLines: $showRouteLines, convexHull: $showConvexHull, traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMap: $isMeshMap)
|
||||
MapSettingsForm(nodeHistory: $showNodeHistory, routeLines: $showRouteLines, convexHull: $showConvexHull, traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMapDistance: $meshMapDistance, meshMap: $isMeshMap)
|
||||
}
|
||||
.onChange(of: (appState.navigationPath)) { newPath in
|
||||
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ struct ChannelForm: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.presentationDetents([.fraction(0.45), .fraction(0.65)])
|
||||
.presentationDetents([.large])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue