mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Three column working point
This commit is contained in:
parent
40ab2b1954
commit
9fccb74f43
10 changed files with 245 additions and 30 deletions
|
|
@ -116,7 +116,6 @@
|
|||
DDB8F4102A9EE5B400230ECE /* Messages.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB8F40F2A9EE5B400230ECE /* Messages.swift */; };
|
||||
DDB8F4122A9EE5DD00230ECE /* UserList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB8F4112A9EE5DD00230ECE /* UserList.swift */; };
|
||||
DDB8F4142A9EE5F000230ECE /* ChannelList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB8F4132A9EE5F000230ECE /* ChannelList.swift */; };
|
||||
DDC18AD12AAAE5920083FE1E /* NodeListDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC18AD02AAAE5920083FE1E /* NodeListDetail.swift */; };
|
||||
DDC2E15826CE248E0042C5E4 /* MeshtasticApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E15726CE248E0042C5E4 /* MeshtasticApp.swift */; };
|
||||
DDC2E15C26CE248F0042C5E4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15B26CE248F0042C5E4 /* Assets.xcassets */; };
|
||||
DDC2E15F26CE248F0042C5E4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15E26CE248F0042C5E4 /* Preview Assets.xcassets */; };
|
||||
|
|
@ -136,6 +135,9 @@
|
|||
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 */; };
|
||||
DDDB263F2AABEE20003AFCB7 /* NodeListSplit.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDB263E2AABEE20003AFCB7 /* NodeListSplit.swift */; };
|
||||
DDDB26422AABF655003AFCB7 /* NodeListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDB26412AABF655003AFCB7 /* NodeListItem.swift */; };
|
||||
DDDB26442AAC0206003AFCB7 /* NodeDetailItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDB26432AAC0206003AFCB7 /* NodeDetailItem.swift */; };
|
||||
DDDB443629F6287000EE2349 /* MapButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDB443529F6287000EE2349 /* MapButtons.swift */; };
|
||||
DDDB443D29F6592F00EE2349 /* NetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDB443C29F6592F00EE2349 /* NetworkManager.swift */; };
|
||||
DDDB444029F79AB000EE2349 /* UserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDB443F29F79AB000EE2349 /* UserDefaults.swift */; };
|
||||
|
|
@ -324,7 +326,6 @@
|
|||
DDB8F4112A9EE5DD00230ECE /* UserList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserList.swift; sourceTree = "<group>"; };
|
||||
DDB8F4132A9EE5F000230ECE /* ChannelList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelList.swift; sourceTree = "<group>"; };
|
||||
DDBA45EC299ED78100DEEDDC /* MeshtasticDataModelV8.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV8.xcdatamodel; sourceTree = "<group>"; };
|
||||
DDC18AD02AAAE5920083FE1E /* NodeListDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeListDetail.swift; sourceTree = "<group>"; };
|
||||
DDC2E15426CE248E0042C5E4 /* Meshtastic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Meshtastic.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DDC2E15726CE248E0042C5E4 /* MeshtasticApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticApp.swift; sourceTree = "<group>"; };
|
||||
DDC2E15B26CE248F0042C5E4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = ../Assets.xcassets; sourceTree = "<group>"; };
|
||||
|
|
@ -353,6 +354,9 @@
|
|||
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>"; };
|
||||
DDDB263E2AABEE20003AFCB7 /* NodeListSplit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeListSplit.swift; sourceTree = "<group>"; };
|
||||
DDDB26412AABF655003AFCB7 /* NodeListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeListItem.swift; sourceTree = "<group>"; };
|
||||
DDDB26432AAC0206003AFCB7 /* NodeDetailItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeDetailItem.swift; sourceTree = "<group>"; };
|
||||
DDDB443529F6287000EE2349 /* MapButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapButtons.swift; sourceTree = "<group>"; };
|
||||
DDDB443C29F6592F00EE2349 /* NetworkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkManager.swift; sourceTree = "<group>"; };
|
||||
DDDB443F29F79AB000EE2349 /* UserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaults.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -460,6 +464,7 @@
|
|||
DD47E3CA26F0E50300029299 /* Nodes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDDB26402AABEF7B003AFCB7 /* Helpers */,
|
||||
DD769E0228D18BF0001A3F05 /* DeviceMetricsLog.swift */,
|
||||
DD4F23CC28779A3C001D37CB /* EnvironmentMetricsLog.swift */,
|
||||
DD2E65252767A01F00E45FC5 /* NodeDetail.swift */,
|
||||
|
|
@ -468,6 +473,7 @@
|
|||
DD73FD1028750779000852D6 /* PositionLog.swift */,
|
||||
DD14E72D2A82A614006E39BC /* RemoteHardware.swift */,
|
||||
6DEDA5592A957B8E00321D2E /* DetectionSensorLog.swift */,
|
||||
DDDB263E2AABEE20003AFCB7 /* NodeListSplit.swift */,
|
||||
);
|
||||
path = Nodes;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -656,6 +662,7 @@
|
|||
DDDB443E29F79A9400EE2349 /* Extensions */,
|
||||
DDC2E1A526CEB32B0042C5E4 /* Helpers */,
|
||||
DDC2E18826CE24EE0042C5E4 /* Model */,
|
||||
DDDB263D2AABD34F003AFCB7 /* Navigation */,
|
||||
DDC4D5662754996200A4208E /* Persistence */,
|
||||
DDAF8C5626ED07740058C060 /* Protobufs */,
|
||||
DDC2E18926CE24F70042C5E4 /* Resources */,
|
||||
|
|
@ -792,6 +799,22 @@
|
|||
path = Mqtt;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDDB263D2AABD34F003AFCB7 /* Navigation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = Navigation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDDB26402AABEF7B003AFCB7 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDDB26412AABF655003AFCB7 /* NodeListItem.swift */,
|
||||
DDDB26432AAC0206003AFCB7 /* NodeDetailItem.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDDB443E29F79A9400EE2349 /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -833,7 +856,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DDDEE5E029DA3E1100A8E078 /* NodeInfoView.swift */,
|
||||
DDC18AD02AAAE5920083FE1E /* NodeListDetail.swift */,
|
||||
);
|
||||
path = Node;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1075,6 +1097,7 @@
|
|||
DD5E5213298EE33B00D21B61 /* deviceonly.pb.swift in Sources */,
|
||||
DD5E5208298EE33B00D21B61 /* rtttl.pb.swift in Sources */,
|
||||
DD6193792863875F00E59241 /* SerialConfig.swift in Sources */,
|
||||
DDDB263F2AABEE20003AFCB7 /* NodeListSplit.swift in Sources */,
|
||||
DDA0B6B2294CDC55001356EC /* Channels.swift in Sources */,
|
||||
DDB8F4102A9EE5B400230ECE /* Messages.swift in Sources */,
|
||||
DD4A911E2708C65400501B7E /* AppSettings.swift in Sources */,
|
||||
|
|
@ -1085,7 +1108,6 @@
|
|||
DD5E520F298EE33B00D21B61 /* cannedmessages.pb.swift in Sources */,
|
||||
DDB75A232A13CDA9006ED576 /* BatteryLevelCompact.swift in Sources */,
|
||||
DDB75A162A0594AD006ED576 /* TileOverlay.swift in Sources */,
|
||||
DDC18AD12AAAE5920083FE1E /* NodeListDetail.swift in Sources */,
|
||||
DDF924CA26FBB953009FE055 /* ConnectedDevice.swift in Sources */,
|
||||
DD3CC6BE28E4CD9800FA9159 /* BatteryGauge.swift in Sources */,
|
||||
DD6193772862F90F00E59241 /* CannedMessagesConfig.swift in Sources */,
|
||||
|
|
@ -1101,6 +1123,7 @@
|
|||
DDB8F4142A9EE5F000230ECE /* ChannelList.swift in Sources */,
|
||||
DDD43FE32A78C8900083A3E9 /* MqttClientProxyManager.swift in Sources */,
|
||||
DD007BB02AA5981000F5FA12 /* NodeInfoEntityExtension.swift in Sources */,
|
||||
DDDB26422AABF655003AFCB7 /* NodeListItem.swift in Sources */,
|
||||
DDDB444629F8A96500EE2349 /* Character.swift in Sources */,
|
||||
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */,
|
||||
DDB6ABDB28B0AC6000384BA1 /* DistanceText.swift in Sources */,
|
||||
|
|
@ -1163,6 +1186,7 @@
|
|||
DD0F791B28713C8A00A6FDAD /* AdminMessageList.swift in Sources */,
|
||||
DD3CC6BC28E366DF00FA9159 /* Meshtastic.xcdatamodeld in Sources */,
|
||||
DDC4C9FF2A8D982900CE201C /* DetectionSensorConfig.swift in Sources */,
|
||||
DDDB26442AAC0206003AFCB7 /* NodeDetailItem.swift in Sources */,
|
||||
DD5E5210298EE33B00D21B61 /* telemetry.pb.swift in Sources */,
|
||||
DD77093F2AA1B146007A8BF0 /* UIColor.swift in Sources */,
|
||||
DD5E5205298EE33B00D21B61 /* mesh.pb.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ extension UserDefaults {
|
|||
UserDefaults.standard.set(newValue, forKey: "meshtasticUsername")
|
||||
}
|
||||
}
|
||||
|
||||
static var preferredPeripheralId: String {
|
||||
get {
|
||||
UserDefaults.standard.string(forKey: "preferredPeripheralId") ?? ""
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@ struct ContentView: View {
|
|||
Label("nodes", systemImage: "flipphone")
|
||||
}
|
||||
.tag(Tab.nodes)
|
||||
NodeListSplit()
|
||||
.tabItem {
|
||||
Label("nodes", systemImage: "flipphone")
|
||||
}
|
||||
.tag(Tab.nodes2)
|
||||
NodeMap()
|
||||
.tabItem {
|
||||
Label("map", systemImage: "map")
|
||||
|
|
@ -51,5 +56,6 @@ enum Tab {
|
|||
case map
|
||||
case ble
|
||||
case nodes
|
||||
case nodes2
|
||||
case settings
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
//
|
||||
// NodeListDetail.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 9/7/23.
|
||||
//
|
||||
|
||||
//import SwiftUI
|
||||
//import CoreLocation
|
||||
//import MapKit
|
||||
//
|
||||
//struct NodeListDetail: View {
|
||||
//
|
||||
// var node: NodeInfoEntity
|
||||
//
|
||||
// var body: some View {
|
||||
//
|
||||
// }
|
||||
//}
|
||||
|
|
@ -24,8 +24,8 @@ struct ChannelMessageList: View {
|
|||
var maxbytes = 228
|
||||
@FocusState var focusedField: Field?
|
||||
|
||||
@ObservedObject var myInfo: MyInfoEntity
|
||||
@ObservedObject var channel: ChannelEntity
|
||||
@StateObject var myInfo: MyInfoEntity
|
||||
@StateObject var channel: ChannelEntity
|
||||
@State var showDeleteMessageAlert = false
|
||||
@State private var deleteMessageId: Int64 = 0
|
||||
@State private var replyMessageId: Int64 = 0
|
||||
|
|
@ -233,7 +233,7 @@ struct ChannelMessageList: View {
|
|||
message.read = true
|
||||
do {
|
||||
try context.save()
|
||||
print("Read message \(message.messageId) ")
|
||||
print("📖 Read message \(message.messageId) ")
|
||||
appState.unreadChannelMessages = myInfo.unreadMessages
|
||||
UIApplication.shared.applicationIconBadgeNumber = appState.unreadChannelMessages + appState.unreadDirectMessages
|
||||
context.refresh(myInfo, mergeChanges: true)
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ struct UserMessageList: View {
|
|||
message.read = true
|
||||
do {
|
||||
try context.save()
|
||||
print("Read message \(message.messageId) ")
|
||||
print("📖 Read message \(message.messageId) ")
|
||||
appState.unreadDirectMessages = user.unreadMessages
|
||||
UIApplication.shared.applicationIconBadgeNumber = appState.unreadChannelMessages + appState.unreadDirectMessages
|
||||
|
||||
|
|
|
|||
30
Meshtastic/Views/Nodes/Helpers/NodeDetailItem.swift
Normal file
30
Meshtastic/Views/Nodes/Helpers/NodeDetailItem.swift
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// NodeDetailItem.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Garth Vander Houwen on 9/8/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import WeatherKit
|
||||
import MapKit
|
||||
import CoreLocation
|
||||
|
||||
struct NodeDetailItem: View {
|
||||
|
||||
var node: NodeInfoEntity
|
||||
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "name", ascending: false)],
|
||||
predicate: NSPredicate(
|
||||
format: "expire == nil || expire >= %@", Date() as NSDate
|
||||
), animation: .none)
|
||||
private var waypoints: FetchedResults<WaypointEntity>
|
||||
|
||||
|
||||
|
||||
var body: some View {
|
||||
|
||||
NavigationStack {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
89
Meshtastic/Views/Nodes/Helpers/NodeListItem.swift
Normal file
89
Meshtastic/Views/Nodes/Helpers/NodeListItem.swift
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
//
|
||||
// NodeListItem.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Garth Vander Houwen on 9/8/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
|
||||
|
||||
|
||||
struct NodeListItem: View {
|
||||
|
||||
@StateObject var node: NodeInfoEntity
|
||||
|
||||
var body: some View {
|
||||
|
||||
NavigationLink(value: node) {
|
||||
let connected: Bool = false //(bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral?.num ?? -1 == node.num)
|
||||
LazyVStack(alignment: .leading) {
|
||||
HStack {
|
||||
VStack(alignment: .leading) {
|
||||
CircleText(text: node.user?.shortName ?? "?", color: Color(UIColor(hex: UInt32(node.num))), circleSize: 65)
|
||||
.padding(.trailing, 5)
|
||||
let deviceMetrics = node.telemetries?.filtered(using: NSPredicate(format: "metricsType == 0"))
|
||||
if deviceMetrics?.count ?? 0 >= 1 {
|
||||
let mostRecent = deviceMetrics?.lastObject as? TelemetryEntity
|
||||
BatteryLevelCompact(batteryLevel: mostRecent?.batteryLevel, font: .caption2, iconFont: .callout, color: .accentColor)
|
||||
}
|
||||
}
|
||||
VStack(alignment: .leading) {
|
||||
Text(node.user?.longName ?? "unknown".localized)
|
||||
.fontWeight(.medium)
|
||||
.font(.callout)
|
||||
if connected {
|
||||
HStack(alignment: .bottom) {
|
||||
Image(systemName: "antenna.radiowaves.left.and.right.circle.fill")
|
||||
.font(.footnote)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.foregroundColor(.green)
|
||||
Text("connected").font(.caption)
|
||||
}
|
||||
}
|
||||
HStack(alignment: .bottom) {
|
||||
Image(systemName: node.isOnline ? "checkmark.circle.fill" : "moon.circle.fill")
|
||||
.font(.footnote)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.foregroundColor(node.isOnline ? .green : .orange)
|
||||
LastHeardText(lastHeard: node.lastHeard)
|
||||
.font(.caption)
|
||||
}
|
||||
// if node.positions?.count ?? 0 > 0 && (bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral?.num ?? -1 != node.num) {
|
||||
// HStack(alignment: .bottom) {
|
||||
// let lastPostion = node.positions!.reversed()[0] as! PositionEntity
|
||||
// let myCoord = CLLocation(latitude: LocationHelper.currentLocation.latitude, longitude: LocationHelper.currentLocation.longitude)
|
||||
// if lastPostion.nodeCoordinate != nil && myCoord.coordinate.longitude != LocationHelper.DefaultLocation.longitude && myCoord.coordinate.latitude != LocationHelper.DefaultLocation.latitude {
|
||||
// let nodeCoord = CLLocation(latitude: lastPostion.nodeCoordinate!.latitude, longitude: lastPostion.nodeCoordinate!.longitude)
|
||||
// let metersAway = nodeCoord.distance(from: myCoord)
|
||||
// Image(systemName: "lines.measurement.horizontal")
|
||||
// .font(.footnote)
|
||||
// .symbolRenderingMode(.hierarchical)
|
||||
// DistanceText(meters: metersAway).font(.caption)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if node.channel > 0 {
|
||||
HStack(alignment: .bottom) {
|
||||
Image(systemName: "fibrechannel")
|
||||
.font(.footnote)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Channel: \(node.channel)")
|
||||
.font(.footnote)
|
||||
}
|
||||
}
|
||||
|
||||
// if !connected {
|
||||
// HStack(alignment: .bottom) { let preset = ModemPresets(rawValue: Int(connectedNode?.loRaConfig?.modemPreset ?? 0))
|
||||
// LoRaSignalStrengthMeter(snr: node.snr, rssi: node.rssi, preset: preset ?? ModemPresets.longFast, compact: true)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding([.top, .bottom])
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,10 @@ import SwiftUI
|
|||
import CoreLocation
|
||||
|
||||
struct NodeList: View {
|
||||
|
||||
init () {
|
||||
//self.bleManager.context = context
|
||||
}
|
||||
@State private var searchText = ""
|
||||
var nodesQuery: Binding<String> {
|
||||
Binding {
|
||||
|
|
@ -86,7 +90,7 @@ struct NodeList: View {
|
|||
Image(systemName: "lines.measurement.horizontal")
|
||||
.font(.footnote)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
DistanceText(meters: metersAway).font(.footnote)
|
||||
DistanceText(meters: metersAway).font(.caption)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -119,7 +123,7 @@ struct NodeList: View {
|
|||
MeshtasticLogo()
|
||||
)
|
||||
.onAppear {
|
||||
self.bleManager.context = context
|
||||
// self.bleManager.context = context
|
||||
}
|
||||
} detail: {
|
||||
if let node = selection {
|
||||
|
|
|
|||
82
Meshtastic/Views/Nodes/NodeListSplit.swift
Normal file
82
Meshtastic/Views/Nodes/NodeListSplit.swift
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// NodeListSplit.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Garth Vander Houwen on 9/8/23.
|
||||
//
|
||||
import SwiftUI
|
||||
import CoreLocation
|
||||
|
||||
struct NodeListSplit: View {
|
||||
|
||||
@State private var columnVisibility = NavigationSplitViewVisibility.all
|
||||
|
||||
@State private var searchText = ""
|
||||
var nodesQuery: Binding<String> {
|
||||
Binding {
|
||||
searchText
|
||||
} set: { newValue in
|
||||
searchText = newValue
|
||||
nodes.nsPredicate = newValue.isEmpty ? nil : NSPredicate(format: "user.longName CONTAINS[c] %@ OR user.shortName CONTAINS[c] %@", newValue, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
|
||||
@FetchRequest(
|
||||
sortDescriptors: [NSSortDescriptor(key: "lastHeard", ascending: false)],
|
||||
animation: .default)
|
||||
|
||||
private var nodes: FetchedResults<NodeInfoEntity>
|
||||
|
||||
@State private var selection: NodeInfoEntity? // Nothing selected by default.
|
||||
|
||||
var body: some View {
|
||||
NavigationSplitView(columnVisibility: $columnVisibility) {
|
||||
|
||||
let connectedNodeNum = Int(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral?.num ?? 0 : 0)
|
||||
let connectedNode = nodes.first(where: { $0.num == connectedNodeNum })
|
||||
List(nodes, id: \.self, selection: $selection) { node in
|
||||
|
||||
NodeListItem(node: node)
|
||||
}
|
||||
.searchable(text: nodesQuery, prompt: "Find a node")
|
||||
.navigationTitle(String.localizedStringWithFormat("nodes %@".localized, String(nodes.count)))
|
||||
.listStyle(.plain)
|
||||
.navigationSplitViewColumnWidth(300)
|
||||
.navigationBarItems(leading:
|
||||
MeshtasticLogo()
|
||||
)
|
||||
} content: {
|
||||
|
||||
if let node = selection {
|
||||
//NodeDetailItem(node: node)
|
||||
NodeDetail(node: node)
|
||||
.navigationSplitViewColumnWidth(300)
|
||||
} else {
|
||||
Text("select.node")
|
||||
}
|
||||
|
||||
} detail: {
|
||||
Text("Content")
|
||||
}
|
||||
.navigationSplitViewStyle(.balanced)
|
||||
|
||||
// } detail: {
|
||||
// VStack {
|
||||
// Button("Detail Only") {
|
||||
// columnVisibility = .detailOnly
|
||||
// }
|
||||
//
|
||||
// Button("Content and Detail") {
|
||||
// columnVisibility = .doubleColumn
|
||||
// }
|
||||
//
|
||||
// Button("Show All") {
|
||||
// columnVisibility = .all
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue