diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 9bcc189e..97cdca18 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ C9A7BC1027759A9600760B50 /* PositionAnnotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A7BC0F27759A9600760B50 /* PositionAnnotationView.swift */; }; C9A88B55278B503C00BD810A /* MapViewModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A88B54278B503C00BD810A /* MapViewModule.swift */; }; C9A88B57278B559900BD810A /* apponly.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A88B56278B559900BD810A /* apponly.pb.swift */; }; + DD0F791B28713C8A00A6FDAD /* AdminMessageList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0F791A28713C8A00A6FDAD /* AdminMessageList.swift */; }; DD17E5DE277D49D400010EC2 /* storeforward.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17E5DC277D49D400010EC2 /* storeforward.pb.swift */; }; DD1BF2F92776FE2E008C8D2F /* UserMessageList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */; }; DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */; }; @@ -99,6 +100,7 @@ C9A7BC0F27759A9600760B50 /* PositionAnnotationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionAnnotationView.swift; sourceTree = ""; }; C9A88B54278B503C00BD810A /* MapViewModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapViewModule.swift; sourceTree = ""; }; C9A88B56278B559900BD810A /* apponly.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = apponly.pb.swift; sourceTree = ""; }; + DD0F791A28713C8A00A6FDAD /* AdminMessageList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdminMessageList.swift; sourceTree = ""; }; DD17E5DC277D49D400010EC2 /* storeforward.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = storeforward.pb.swift; sourceTree = ""; }; DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserMessageList.swift; sourceTree = ""; }; DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeripheralModel.swift; sourceTree = ""; }; @@ -244,6 +246,7 @@ DD8169FE272476C700F4AB02 /* LogDocument.swift */, DD6B85A728009258000ACD6B /* ShareChannel.swift */, DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */, + DD0F791A28713C8A00A6FDAD /* AdminMessageList.swift */, DD61937A2863876A00E59241 /* Config */, ); path = Settings; @@ -659,6 +662,7 @@ DD47E3D926F3093800029299 /* MessageBubble.swift in Sources */, DD415828285859C4009B0E59 /* TelemetryConfig.swift in Sources */, C9697F9D279336B700250207 /* LocalMBTileOverlay.swift in Sources */, + DD0F791B28713C8A00A6FDAD /* AdminMessageList.swift in Sources */, DD8169F9271F1A6100F4AB02 /* MeshLogger.swift in Sources */, DD539502276DAA6A00AD86B1 /* MapLocation.swift in Sources */, DD41582A28585C32009B0E59 /* RangeTestConfig.swift in Sources */, diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index e3f5f7ed..81176b23 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -960,7 +960,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph if connectedPeripheral!.peripheral.state == CBPeripheralState.connected { let newMessage = MessageEntity(context: context!) - newMessage.messageId = Int64(UInt32.random(in: UInt32(UInt8.max).. - + diff --git a/Meshtastic/Persistence/UserEntityExtension.swift b/Meshtastic/Persistence/UserEntityExtension.swift index 263140ba..0298cffc 100644 --- a/Meshtastic/Persistence/UserEntityExtension.swift +++ b/Meshtastic/Persistence/UserEntityExtension.swift @@ -13,4 +13,9 @@ extension UserEntity { self.value(forKey: "allMessages") as! [MessageEntity] } + + var adminMessageList: [MessageEntity] { + + self.value(forKey: "adminMessages") as! [MessageEntity] + } } diff --git a/Meshtastic/Views/Helpers/DateTimeText.swift b/Meshtastic/Views/Helpers/DateTimeText.swift index cbd57004..e88a46e6 100644 --- a/Meshtastic/Views/Helpers/DateTimeText.swift +++ b/Meshtastic/Views/Helpers/DateTimeText.swift @@ -1,8 +1,8 @@ // // DateTimeText.swift -// MeshtasticApple +// Meshtastic Apple // -// Created by Garth Vander Houwen on 5/30/22. +// Copyright(C) Garth Vander Houwen 5/30/22. // import SwiftUI diff --git a/Meshtastic/Views/Messages/Contacts.swift b/Meshtastic/Views/Messages/Contacts.swift index f4f2b0e7..2b724f14 100644 --- a/Meshtastic/Views/Messages/Contacts.swift +++ b/Meshtastic/Views/Messages/Contacts.swift @@ -24,16 +24,15 @@ struct Contacts: View { List(users) { (user: UserEntity) in - let allMessages = user.value(forKey: "allMessages") as! [MessageEntity] let connectedNodeNum = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.num : 0 if user.num != connectedNodeNum { NavigationLink(destination: UserMessageList(user: user)) { - if allMessages.count > 0 { + if user.messageList.count > 0 { - let mostRecent = allMessages.last + let mostRecent = user.messageList.last let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64((mostRecent!.messageTimestamp )))) let lastMessageDay = Calendar.current.dateComponents([.day], from: lastMessageTime).day ?? 0 let currentDay = Calendar.current.dateComponents([.day], from: Date()).day ?? 0 diff --git a/Meshtastic/Views/Settings/AdminMessageList.swift b/Meshtastic/Views/Settings/AdminMessageList.swift new file mode 100644 index 00000000..582a5251 --- /dev/null +++ b/Meshtastic/Views/Settings/AdminMessageList.swift @@ -0,0 +1,72 @@ +// +// AdminMessageList.swift +// Meshtastic +// +// Created by Garth Vander Houwen on 7/2/22. +// +/* +Abstract: +A view showing the details for a node. +*/ + +import SwiftUI +import MapKit +import CoreLocation + +struct AdminMessageList: View { + + @Environment(\.managedObjectContext) var context + + @EnvironmentObject var bleManager: BLEManager + + var user: UserEntity? + + var body: some View { + + List { + if user != nil { + + ForEach ( user!.adminMessageList ) { am in + + HStack { + + Text("\(am.adminDescription ?? "Unknown") - \(Date(timeIntervalSince1970: TimeInterval(am.messageTimestamp)), style: .date) \(Date(timeIntervalSince1970: TimeInterval(am.messageTimestamp)), style: .time)") + .font(.caption) + + if am.receivedACK { + + Image(systemName: "checkmark.square") + .foregroundColor(.gray) + .font(.caption) + Text("Acknowledged: ") + .foregroundColor(.gray) + .font(.caption) + DateTimeText(dateTime: Date(timeIntervalSince1970: TimeInterval(am.messageTimestamp))) + .foregroundColor(.gray) + .font(.caption) + + } else { + Image(systemName: "square") + .foregroundColor(.gray) + .font(.caption) + Text("Acknowledged") + .foregroundColor(.gray) + .font(.caption) + } + } + } + } + } + .navigationTitle("Admin Message History") + .navigationBarItems(trailing: + + ZStack { + + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") + }) + .onAppear { + + self.bleManager.context = context + } + } +} diff --git a/Meshtastic/Views/Settings/AppSettings.swift b/Meshtastic/Views/Settings/AppSettings.swift index bc410981..a9f6dc04 100644 --- a/Meshtastic/Views/Settings/AppSettings.swift +++ b/Meshtastic/Views/Settings/AppSettings.swift @@ -156,12 +156,6 @@ struct AppSettings: View { .pickerStyle(DefaultPickerStyle()) } - Section(header: Text("DEBUG")) { - - NavigationLink(destination: MeshLog()) { - Text("View Mesh Log") - } - } } } .navigationTitle("App Settings") diff --git a/Meshtastic/Views/Settings/MeshLog.swift b/Meshtastic/Views/Settings/MeshLog.swift index 4bb8251a..b8eee16b 100644 --- a/Meshtastic/Views/Settings/MeshLog.swift +++ b/Meshtastic/Views/Settings/MeshLog.swift @@ -42,7 +42,7 @@ struct MeshLog: View { ) .textSelection(.enabled) - .font(.caption2) + .font(.caption) HStack(alignment: .center) { Spacer() diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index 071eea8d..43f4341b 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -25,27 +25,17 @@ struct Settings: View { let connectedNodeNum = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.num : 0 - Section("General") { - NavigationLink { - AppSettings() - } label: { - - Image(systemName: "gearshape") - .symbolRenderingMode(.hierarchical) - Text("App Settings") - } - Text("Apple app specific settings and features, app username, share position with mesh options, map and keyboard type, mesh log.") - .font(.caption) - .fixedSize(horizontal: false, vertical: true) - + NavigationLink { + AppSettings() + } label: { + + Image(systemName: "gearshape") + .symbolRenderingMode(.hierarchical) + Text("App Settings") } Section("Radio Configuration") { - Text("Radio config views will be be enabled when there is a connected node. Save buttons will be enabled when there are config changes to save.") - .font(.caption) - .fixedSize(horizontal: false, vertical: true) - NavigationLink { ShareChannel(node: nodes.first(where: { $0.num == connectedNodeNum }) ?? NodeInfoEntity()) } label: { @@ -109,7 +99,7 @@ struct Settings: View { } .disabled(bleManager.connectedPeripheral == nil) - Text("Default settings values are prefered whenever possible as they consume no bandwidth when sent over the mesh.") + Text("Default settings values are prefered as they consume no bandwidth when sent over the mesh.") .font(.caption2) .fixedSize(horizontal: false, vertical: true) } @@ -173,6 +163,35 @@ struct Settings: View { } .disabled(bleManager.connectedPeripheral == nil) } + Section(header: Text("Logging")) { + + NavigationLink { + + MeshLog() + + } label: { + + Image(systemName: "list.bullet.rectangle") + .symbolRenderingMode(.hierarchical) + + Text("Mesh Log") + } + + NavigationLink { + + let connectedNode = nodes.first(where: { $0.num == connectedNodeNum }) + + AdminMessageList(user: connectedNode?.user ?? UserEntity()) + } label: { + + Image(systemName: "building.columns") + .symbolRenderingMode(.hierarchical) + + Text("Admin Message Log") + } + .disabled(bleManager.connectedPeripheral == nil) + } + // Not Implemented: // Store Forward Config - Not Working, TBEAM Only // WiFi Config - Would break connection to device