mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Add favorite and distance filter to the node list
This commit is contained in:
parent
ee891f62c7
commit
78c0bca781
5 changed files with 62 additions and 39 deletions
|
|
@ -14,7 +14,7 @@ extension MyInfoEntity {
|
|||
}
|
||||
|
||||
var unreadMessages: Int {
|
||||
let unreadMessages = messageList.filter{ ($0 as AnyObject).read == false }
|
||||
let unreadMessages = messageList.filter{ ($0 as AnyObject).read == false && ($0 as AnyObject).isEmoji == false }
|
||||
return unreadMessages.count
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ struct NodeListFilter: View {
|
|||
@Binding var viaLora: Bool
|
||||
@Binding var viaMqtt: Bool
|
||||
@Binding var isOnline: Bool
|
||||
@Binding var isFavorite: Bool
|
||||
@Binding var distanceFilter: Bool
|
||||
@Binding var maximumDistance: Double
|
||||
@Binding var hopsAway: Int
|
||||
|
|
@ -48,7 +49,7 @@ struct NodeListFilter: View {
|
|||
Toggle(isOn: $isOnline) {
|
||||
|
||||
Label {
|
||||
Text("Online Only")
|
||||
Text("Online")
|
||||
} icon: {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
.foregroundColor(.green)
|
||||
|
|
@ -58,29 +59,43 @@ struct NodeListFilter: View {
|
|||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
.listRowSeparator(.visible)
|
||||
|
||||
// Toggle(isOn: $distanceFilter) {
|
||||
//
|
||||
// Label {
|
||||
// Text("Distance")
|
||||
// } icon: {
|
||||
// Image(systemName: "map")
|
||||
// }
|
||||
// }
|
||||
// .toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
//
|
||||
// .listRowSeparator(distanceFilter ? .hidden : .visible)
|
||||
// if distanceFilter {
|
||||
// HStack {
|
||||
// Label("Show nodes", systemImage: "lines.measurement.horizontal")
|
||||
// Picker("", selection: $maximumDistance) {
|
||||
// ForEach(MeshMapDistances.allCases) { di in
|
||||
// Text(di.description)
|
||||
// .tag(di.id)
|
||||
// }
|
||||
// }
|
||||
// .pickerStyle(DefaultPickerStyle())
|
||||
// }
|
||||
// }
|
||||
Toggle(isOn: $isFavorite) {
|
||||
|
||||
Label {
|
||||
Text("Favorites")
|
||||
} icon: {
|
||||
|
||||
Image(systemName: "star.fill")
|
||||
.foregroundColor(.yellow)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
}
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
.listRowSeparator(.visible)
|
||||
|
||||
Toggle(isOn: $distanceFilter) {
|
||||
|
||||
Label {
|
||||
Text("Distance")
|
||||
} icon: {
|
||||
Image(systemName: "map")
|
||||
}
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
.listRowSeparator(distanceFilter ? .hidden : .visible)
|
||||
if distanceFilter {
|
||||
HStack {
|
||||
Label("Show nodes", systemImage: "lines.measurement.horizontal")
|
||||
Picker("", selection: $maximumDistance) {
|
||||
ForEach(MeshMapDistances.allCases) { di in
|
||||
Text(di.description)
|
||||
.tag(di.id)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
Label("Hops Away", systemImage: "hare")
|
||||
Picker("", selection: $hopsAway) {
|
||||
|
|
@ -125,7 +140,7 @@ struct NodeListFilter: View {
|
|||
.padding(.bottom)
|
||||
#endif
|
||||
}
|
||||
.presentationDetents([.fraction(0.40), .fraction(0.50)])
|
||||
.presentationDetents([.fraction(0.6), .fraction(0.75)])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ struct NodeList: View {
|
|||
@State private var viaLora = true
|
||||
@State private var viaMqtt = true
|
||||
@State private var isOnline = false
|
||||
@State private var isFavorite = false
|
||||
@State private var distanceFilter = false
|
||||
@State private var maxDistance: Double = 800000
|
||||
@State private var hopsAway: Int = -1
|
||||
|
|
@ -33,7 +34,9 @@ struct NodeList: View {
|
|||
@EnvironmentObject var bleManager: BLEManager
|
||||
|
||||
@FetchRequest(
|
||||
sortDescriptors: [NSSortDescriptor(key: "favorite", ascending: false), NSSortDescriptor(key: "lastHeard", ascending: false)],
|
||||
sortDescriptors: [NSSortDescriptor(key: "favorite", ascending: false),
|
||||
NSSortDescriptor(key: "lastHeard", ascending: false),
|
||||
NSSortDescriptor(key: "user.longName", ascending: true)],
|
||||
animation: .default)
|
||||
|
||||
var nodes: FetchedResults<NodeInfoEntity>
|
||||
|
|
@ -164,7 +167,7 @@ struct NodeList: View {
|
|||
}
|
||||
}
|
||||
.sheet(isPresented: $isEditingFilters) {
|
||||
NodeListFilter(viaLora: $viaLora, viaMqtt: $viaMqtt, isOnline: $isOnline, distanceFilter: $distanceFilter, maximumDistance: $maxDistance, hopsAway: $hopsAway, deviceRole: $deviceRole)
|
||||
NodeListFilter(viaLora: $viaLora, viaMqtt: $viaMqtt, isOnline: $isOnline, isFavorite: $isFavorite, distanceFilter: $distanceFilter, maximumDistance: $maxDistance, hopsAway: $hopsAway, deviceRole: $deviceRole)
|
||||
}
|
||||
.safeAreaInset(edge: .bottom, alignment: .trailing) {
|
||||
HStack {
|
||||
|
|
@ -282,6 +285,12 @@ struct NodeList: View {
|
|||
.onChange(of: isOnline) { _ in
|
||||
searchNodeList()
|
||||
}
|
||||
.onChange(of: isFavorite) { _ in
|
||||
searchNodeList()
|
||||
}
|
||||
.onChange(of: maxDistance) { _ in
|
||||
searchNodeList()
|
||||
}
|
||||
.onAppear {
|
||||
if self.bleManager.context == nil {
|
||||
self.bleManager.context = context
|
||||
|
|
@ -325,6 +334,11 @@ struct NodeList: View {
|
|||
let isOnlinePredicate = NSPredicate(format: "lastHeard >= %@", Calendar.current.date(byAdding: .minute, value: -15, to: Date())! as NSDate)
|
||||
predicates.append(isOnlinePredicate)
|
||||
}
|
||||
/// Favorites
|
||||
if isFavorite {
|
||||
let isFavoritePredicate = NSPredicate(format: "favorite == YES")
|
||||
predicates.append(isFavoritePredicate)
|
||||
}
|
||||
/// Distance
|
||||
if distanceFilter {
|
||||
let pointOfInterest = LocationHelper.currentLocation
|
||||
|
|
@ -339,15 +353,12 @@ struct NodeList: View {
|
|||
let maxLatitude: Double = pointOfInterest.latitude + deltaLatitude
|
||||
let minLongitude: Double = pointOfInterest.longitude - deltaLongitude
|
||||
let maxLongitude: Double = pointOfInterest.longitude + deltaLongitude
|
||||
let distancePredicate = NSPredicate(format: "(%lf <= (positions[first].longitudeI / 1e7))", minLongitude, maxLongitude,minLatitude, maxLatitude)
|
||||
//let distancePredicate = NSPredicate(format: "(%lf <= (positions[LAST].longitudeI / 1e7)) AND ((positions[LAST].longitudeI / 1e7) <= %lf) AND (%lf <= (positions[LAST].latitudeI / 1e7)) AND ((positions[LAST].latitudeI / 1e7) <= %lf)", minLongitude, maxLongitude,minLatitude, maxLatitude)
|
||||
|
||||
//predicates.append(distancePredicate)
|
||||
let distancePredicate = NSPredicate(format: "(SUBQUERY(positions, $position, $position.latest == TRUE && (%lf <= ($position.longitudeI / 1e7)) AND (($position.longitudeI / 1e7) <= %lf) AND (%lf <= ($position.latitudeI / 1e7)) AND (($position.latitudeI / 1e7) <= %lf))).@count > 0", minLongitude, maxLongitude,minLatitude, maxLatitude)
|
||||
predicates.append(distancePredicate)
|
||||
}
|
||||
}
|
||||
|
||||
if predicates.count > 0 || !searchText.isEmpty {
|
||||
|
||||
if !searchText.isEmpty {
|
||||
let filterPredicates = NSCompoundPredicate(type: .and, subpredicates: predicates)
|
||||
nodes.nsPredicate = NSCompoundPredicate(type: .and, subpredicates: [textSearchPredicate, filterPredicates])
|
||||
|
|
|
|||
|
|
@ -134,6 +134,8 @@ struct Channels: View {
|
|||
.padding()
|
||||
#endif
|
||||
ChannelForm(channelIndex: $channelIndex, channelName: $channelName, channelKeySize: $channelKeySize, channelKey: $channelKey, channelRole: $channelRole, uplink: $uplink, downlink: $downlink, positionPrecision: $positionPrecision, preciseLocation: $preciseLocation, positionsEnabled: $positionsEnabled, hasChanges: $hasChanges, hasValidKey: $hasValidKey, supportedVersion: $supportedVersion)
|
||||
.presentationDetents([.large])
|
||||
.presentationDragIndicator(.visible)
|
||||
.onAppear {
|
||||
supportedVersion = bleManager.connectedVersion == "0.0.0" || self.minimumVersion.compare(bleManager.connectedVersion, options: .numeric) == .orderedAscending || minimumVersion.compare(bleManager.connectedVersion, options: .numeric) == .orderedSame
|
||||
}
|
||||
|
|
@ -149,8 +151,6 @@ struct Channels: View {
|
|||
channel.settings.uplinkEnabled = uplink
|
||||
channel.settings.downlinkEnabled = downlink
|
||||
channel.settings.moduleSettings.positionPrecision = UInt32(positionPrecision)
|
||||
|
||||
|
||||
|
||||
guard let mutableChannels = node?.myInfo?.channels?.mutableCopy() as? NSMutableOrderedSet else {
|
||||
return
|
||||
|
|
@ -221,8 +221,6 @@ struct Channels: View {
|
|||
.padding(.bottom)
|
||||
#endif
|
||||
}
|
||||
.presentationDetents([.fraction(0.85), .large])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
if node?.myInfo?.channels?.array.count ?? 0 < 8 && node != nil {
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ struct ChannelForm: View {
|
|||
|
||||
)
|
||||
.onChange(of: channelKey, perform: { _ in
|
||||
|
||||
let tempKey = Data(base64Encoded: channelKey) ?? Data()
|
||||
if tempKey.count == channelKeySize || channelKeySize == -1{
|
||||
hasValidKey = true
|
||||
|
|
@ -245,7 +246,5 @@ struct ChannelForm: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.presentationDetents([.large])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue