mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #206 from meshtastic/messages_cleanup
Messages cleanup
This commit is contained in:
commit
a44ad6eceb
15 changed files with 341 additions and 351 deletions
|
|
@ -17,7 +17,7 @@
|
|||
DD17E5DE277D49D400010EC2 /* storeforward.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD17E5DC277D49D400010EC2 /* storeforward.pb.swift */; };
|
||||
DD1925B728CDA5A400720036 /* CannedMessagesConfigEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1925B628CDA5A400720036 /* CannedMessagesConfigEnums.swift */; };
|
||||
DD1925B928CDA93900720036 /* SerialConfigEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1925B828CDA93900720036 /* SerialConfigEnums.swift */; };
|
||||
DD1BF2F92776FE2E008C8D2F /* UserMessageList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */; };
|
||||
DD1BF2F92776FE2E008C8D2F /* MessageList.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1BF2F82776FE2E008C8D2F /* MessageList.swift */; };
|
||||
DD2160AF28C5552500C17253 /* MQTTConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2160AE28C5552500C17253 /* MQTTConfig.swift */; };
|
||||
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */; };
|
||||
DD2553572855B02500E55709 /* LoRaConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2553562855B02500E55709 /* LoRaConfig.swift */; };
|
||||
|
|
@ -131,7 +131,7 @@
|
|||
DD17E5DC277D49D400010EC2 /* storeforward.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = storeforward.pb.swift; sourceTree = "<group>"; };
|
||||
DD1925B628CDA5A400720036 /* CannedMessagesConfigEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CannedMessagesConfigEnums.swift; sourceTree = "<group>"; };
|
||||
DD1925B828CDA93900720036 /* SerialConfigEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerialConfigEnums.swift; sourceTree = "<group>"; };
|
||||
DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserMessageList.swift; sourceTree = "<group>"; };
|
||||
DD1BF2F82776FE2E008C8D2F /* MessageList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageList.swift; sourceTree = "<group>"; };
|
||||
DD2160AE28C5552500C17253 /* MQTTConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTConfig.swift; sourceTree = "<group>"; };
|
||||
DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeripheralModel.swift; sourceTree = "<group>"; };
|
||||
DD2553562855B02500E55709 /* LoRaConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoRaConfig.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -497,7 +497,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DD882F5C2772E4640005BF05 /* Contacts.swift */,
|
||||
DD1BF2F82776FE2E008C8D2F /* UserMessageList.swift */,
|
||||
DD1BF2F82776FE2E008C8D2F /* MessageList.swift */,
|
||||
);
|
||||
path = Messages;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -731,7 +731,7 @@
|
|||
DD6193772862F90F00E59241 /* CannedMessagesConfig.swift in Sources */,
|
||||
DD41582628582E9B009B0E59 /* DeviceConfig.swift in Sources */,
|
||||
DD3CC6B528E33FD100FA9159 /* ShareChannels.swift in Sources */,
|
||||
DD1BF2F92776FE2E008C8D2F /* UserMessageList.swift in Sources */,
|
||||
DD1BF2F92776FE2E008C8D2F /* MessageList.swift in Sources */,
|
||||
DD3CC6C228EB9D4900FA9159 /* UpdateCoreData.swift in Sources */,
|
||||
DDB6ABE628B1406100384BA1 /* LoraConfigEnums.swift in Sources */,
|
||||
DDB2CC6E27F3EB47009C5FCC /* telemetry.pb.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
var timeoutTimer: Timer?
|
||||
var timeoutTimerCount = 0
|
||||
var positionTimer: Timer?
|
||||
let broadcastNodeNum: UInt32 = 4294967295
|
||||
let broadcastNodeNum: UInt32 = 0
|
||||
|
||||
/* Meshtastic Service Details */
|
||||
var TORADIO_characteristic: CBCharacteristic!
|
||||
|
|
@ -531,7 +531,9 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
} else {
|
||||
|
||||
let myInfo = myInfoPacket(myInfo: decodedInfo.myInfo, meshLogging: meshLoggingEnabled, context: context!)
|
||||
let myInfo = myInfoPacket(myInfo: decodedInfo.myInfo, peripheralId: self.connectedPeripheral.id, meshLogging: meshLoggingEnabled, context: context!)
|
||||
|
||||
self.userSettings?.preferredNodeNum = myInfo?.myNodeNum ?? 0
|
||||
|
||||
if myInfo != nil {
|
||||
|
||||
|
|
@ -675,11 +677,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
// Use a RunLoop to prevent the timer from running on the main UI thread
|
||||
if userSettings?.provideLocation ?? false {
|
||||
if self.positionTimer != nil {
|
||||
|
||||
|
||||
self.positionTimer!.invalidate()
|
||||
}
|
||||
let context = ["name": "@\(peripheral.name ?? "Unknown")"]
|
||||
self.positionTimer = Timer.scheduledTimer(timeInterval: TimeInterval((userSettings?.provideLocationInterval ?? 900)), target: self, selector: #selector(positionTimerFired), userInfo: context, repeats: true)
|
||||
positionTimer = Timer.scheduledTimer(timeInterval: TimeInterval((userSettings?.provideLocationInterval ?? 900)), target: self, selector: #selector(positionTimerFired), userInfo: context, repeats: true)
|
||||
RunLoop.current.add(self.positionTimer!, forMode: .common)
|
||||
}
|
||||
|
||||
|
|
@ -922,12 +923,12 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
toRadio.packet = meshPacket
|
||||
let binaryData: Data = try! toRadio.serializedData()
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("📍 Sent a Position Packet from the Apple device GPS to node: \(fromNodeNum)") }
|
||||
|
||||
if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
|
||||
|
||||
connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
|
||||
success = true
|
||||
MeshLogger.log("📍 Sent a Share Location Position Packet from the Apple device GPS to node: \(fromNodeNum)")
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class LocationHelper: NSObject, ObservableObject {
|
|||
static let DefaultAltitude = CLLocationDistance(integerLiteral: 0)
|
||||
static let DefaultSpeed = CLLocationSpeed(integerLiteral: 0)
|
||||
static let DefaultHeading = CLLocationDirection(integerLiteral: 0)
|
||||
static let DefaultTime = Date.init(timeIntervalSince1970: 0)
|
||||
|
||||
static var currentLocation: CLLocationCoordinate2D {
|
||||
|
||||
|
|
@ -47,7 +46,7 @@ class LocationHelper: NSObject, ObservableObject {
|
|||
static var currentTimestamp: Date {
|
||||
|
||||
guard let timestamp = shared.locationManager.location?.timestamp else {
|
||||
return DefaultTime
|
||||
return Date.now
|
||||
}
|
||||
return timestamp
|
||||
}
|
||||
|
|
|
|||
|
|
@ -743,7 +743,7 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
}
|
||||
}
|
||||
|
||||
func myInfoPacket (myInfo: MyNodeInfo, meshLogging: Bool, context: NSManagedObjectContext) -> MyInfoEntity? {
|
||||
func myInfoPacket (myInfo: MyNodeInfo, peripheralId: String, meshLogging: Bool, context: NSManagedObjectContext) -> MyInfoEntity? {
|
||||
|
||||
let fetchMyInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MyInfoEntity")
|
||||
fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(myInfo.myNodeNum))
|
||||
|
|
@ -754,6 +754,7 @@ func myInfoPacket (myInfo: MyNodeInfo, meshLogging: Bool, context: NSManagedObje
|
|||
if fetchedMyInfo.isEmpty {
|
||||
|
||||
let myInfoEntity = MyInfoEntity(context: context)
|
||||
myInfoEntity.peripheralId = peripheralId
|
||||
myInfoEntity.myNodeNum = Int64(myInfo.myNodeNum)
|
||||
myInfoEntity.hasGps = myInfo.hasGps_p
|
||||
myInfoEntity.hasWifi = myInfo.hasWifi_p
|
||||
|
|
@ -784,6 +785,7 @@ func myInfoPacket (myInfo: MyNodeInfo, meshLogging: Bool, context: NSManagedObje
|
|||
|
||||
} else {
|
||||
|
||||
fetchedMyInfo[0].peripheralId = peripheralId
|
||||
fetchedMyInfo[0].myNodeNum = Int64(myInfo.myNodeNum)
|
||||
fetchedMyInfo[0].hasGps = myInfo.hasGps_p
|
||||
fetchedMyInfo[0].bitrate = myInfo.bitrate
|
||||
|
|
@ -1187,6 +1189,11 @@ func positionPacket (packet: MeshPacket, meshLogging: Bool, context: NSManagedOb
|
|||
} else {
|
||||
|
||||
print("💥 Empty POSITION_APP Packet")
|
||||
|
||||
if let dataMessage = try? DataMessage(serializedData: packet.decoded.payload) {
|
||||
print(dataMessage)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@
|
|||
<attribute name="messageTimeoutMsec" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="minAppVersion" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="myNodeNum" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="peripheralId" optional="YES" attributeType="String"/>
|
||||
<attribute name="rebootCount" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="channels" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="ChannelEntity" inverseName="myInfoChannel" inverseEntity="ChannelEntity"/>
|
||||
<relationship name="myInfoNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="myInfo" inverseEntity="NodeInfoEntity"/>
|
||||
|
|
@ -224,7 +225,6 @@
|
|||
<attribute name="macaddr" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="shortName" attributeType="String"/>
|
||||
<attribute name="team" optional="YES" attributeType="String"/>
|
||||
<attribute name="userId" attributeType="String"/>
|
||||
<relationship name="receivedMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="toUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="sentMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="fromUser" inverseEntity="MessageEntity"/>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ class UserSettings: ObservableObject {
|
|||
UserDefaults.standard.set(preferredPeripheralId, forKey: "preferredPeripheralId")
|
||||
}
|
||||
}
|
||||
@Published var preferredNodeNum: Int64 {
|
||||
didSet {
|
||||
UserDefaults.standard.set(preferredNodeNum, forKey: "preferredNodeNum")
|
||||
}
|
||||
}
|
||||
@Published var provideLocation: Bool {
|
||||
didSet {
|
||||
UserDefaults.standard.set(provideLocation, forKey: "provideLocation")
|
||||
|
|
@ -48,6 +53,7 @@ class UserSettings: ObservableObject {
|
|||
|
||||
self.meshtasticUsername = UserDefaults.standard.object(forKey: "meshtasticusername") as? String ?? ""
|
||||
self.preferredPeripheralId = UserDefaults.standard.object(forKey: "preferredPeripheralId") as? String ?? ""
|
||||
self.preferredNodeNum = UserDefaults.standard.object(forKey: "preferredNodeNum") as? Int64 ?? 0
|
||||
self.provideLocation = UserDefaults.standard.object(forKey: "provideLocation") as? Bool ?? false
|
||||
self.provideLocationInterval = UserDefaults.standard.object(forKey: "provideLocationInterval") as? Int ?? 900
|
||||
self.keyboardType = UserDefaults.standard.object(forKey: "keyboardType") as? Int ?? 0
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ struct Connect: View {
|
|||
|
||||
|
||||
userSettings.preferredPeripheralId = bleManager.connectedPeripheral!.peripheral.identifier.uuidString
|
||||
userSettings.preferredNodeNum = bleManager.connectedPeripheral!.num
|
||||
bleManager.preferredPeripheral = true
|
||||
isPreferredRadio = true
|
||||
|
||||
|
|
@ -100,6 +101,7 @@ struct Connect: View {
|
|||
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.identifier.uuidString == userSettings.preferredPeripheralId {
|
||||
|
||||
userSettings.preferredPeripheralId = ""
|
||||
userSettings.preferredNodeNum = 0
|
||||
bleManager.preferredPeripheral = false
|
||||
isPreferredRadio = false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ Copyright (c) Garth Vander Houwen 2021
|
|||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@State private var selection: Tab = .ble
|
||||
|
||||
@EnvironmentObject var userSettings: UserSettings
|
||||
|
||||
@State private var selection: Tab = .ble
|
||||
|
||||
enum Tab {
|
||||
case contacts
|
||||
|
|
@ -15,18 +18,24 @@ struct ContentView: View {
|
|||
case nodes
|
||||
case settings
|
||||
}
|
||||
|
||||
|
||||
|
||||
var body: some View {
|
||||
|
||||
TabView(selection: $selection) {
|
||||
Contacts()
|
||||
|
||||
if userSettings.preferredNodeNum > 0 {
|
||||
|
||||
Contacts()
|
||||
.tabItem {
|
||||
Label("Messages", systemImage: "message")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.symbolVariant(.none)
|
||||
|
||||
|
||||
}
|
||||
.tag(Tab.contacts)
|
||||
}
|
||||
Connect()
|
||||
.tabItem {
|
||||
Label("Bluetooth", systemImage: "antenna.radiowaves.left.and.right")
|
||||
|
|
@ -34,28 +43,32 @@ struct ContentView: View {
|
|||
.symbolVariant(.none)
|
||||
}
|
||||
.tag(Tab.ble)
|
||||
NodeList()
|
||||
.tabItem {
|
||||
Label("Nodes", systemImage: "flipphone")
|
||||
NodeList()
|
||||
.tabItem {
|
||||
Label("Nodes", systemImage: "flipphone")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.symbolVariant(.none)
|
||||
}
|
||||
.tag(Tab.nodes)
|
||||
NodeMap()
|
||||
.tabItem {
|
||||
Label("Mesh Map", systemImage: "map")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.symbolVariant(.none)
|
||||
}
|
||||
.tag(Tab.map)
|
||||
Settings()
|
||||
.tabItem {
|
||||
Label("Settings", systemImage: "gear")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.symbolVariant(.none)
|
||||
}
|
||||
.tag(Tab.settings)
|
||||
}
|
||||
.tag(Tab.nodes)
|
||||
NodeMap()
|
||||
.tabItem {
|
||||
Label("Mesh Map", systemImage: "map")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.symbolVariant(.none)
|
||||
}
|
||||
.tag(Tab.map)
|
||||
Settings()
|
||||
.tabItem {
|
||||
Label("Settings", systemImage: "gear")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.symbolVariant(.none)
|
||||
}
|
||||
.tag(Tab.settings)
|
||||
|
||||
}
|
||||
.onAppear(
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
#if canImport(Charts)
|
||||
import Charts
|
||||
#endif
|
||||
|
||||
struct BatteryGauge: View {
|
||||
|
||||
|
|
@ -18,6 +20,7 @@ struct BatteryGauge: View {
|
|||
var body: some View {
|
||||
VStack {
|
||||
|
||||
#if !targetEnvironment(macCatalyst)
|
||||
if batteryLevel == 0.0 {
|
||||
// Plugged in
|
||||
Image(systemName: "powerplug")
|
||||
|
|
@ -47,6 +50,7 @@ struct BatteryGauge: View {
|
|||
.tint(gradient)
|
||||
.gaugeStyle(.accessoryCircular)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,126 +11,120 @@ struct Contacts: View {
|
|||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
|
||||
@State var onboarding = true
|
||||
|
||||
@FetchRequest(
|
||||
sortDescriptors: [NSSortDescriptor(key: "longName", ascending: true)],
|
||||
animation: .default)
|
||||
|
||||
private var users: FetchedResults<UserEntity>
|
||||
|
||||
@FetchRequest(
|
||||
sortDescriptors: [NSSortDescriptor(key: "lastHeard", ascending: true)],
|
||||
animation: .default)
|
||||
|
||||
private var nodes: FetchedResults<NodeInfoEntity>
|
||||
|
||||
var body: some View {
|
||||
|
||||
NavigationView {
|
||||
|
||||
// Display Contact for Primary Channel
|
||||
// Display Contacts for DM's on the Primary Channel
|
||||
// Display Contacts for the rest of the non admin channels
|
||||
|
||||
List {
|
||||
ForEach(users) { (user: UserEntity) in
|
||||
|
||||
let connectedNodeNum = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.num : 0
|
||||
|
||||
if user.num != connectedNodeNum {
|
||||
|
||||
NavigationLink(destination: UserMessageList(user: user)) {
|
||||
|
||||
if user.messageList.count > 0 {
|
||||
Section(header: Text("Primary Channel")) {
|
||||
|
||||
ForEach(users) { (user: UserEntity) in
|
||||
|
||||
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
|
||||
if user.num != bleManager.userSettings?.preferredNodeNum ?? 0 {
|
||||
|
||||
HStack {
|
||||
|
||||
VStack {
|
||||
|
||||
CircleText(text: user.shortName ?? "???", color: Color.blue)
|
||||
}
|
||||
.padding([.leading, .trailing])
|
||||
|
||||
VStack {
|
||||
NavigationLink(destination: MessageList(user: user)) {
|
||||
|
||||
HStack {
|
||||
|
||||
VStack {
|
||||
|
||||
Text(user.longName ?? "Unknown").font(.headline).fixedSize()
|
||||
}
|
||||
|
||||
VStack {
|
||||
|
||||
if lastMessageDay == currentDay {
|
||||
|
||||
Text(lastMessageTime, style: .time )
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
|
||||
} else if lastMessageDay == (currentDay - 1) {
|
||||
|
||||
Text("Yesterday")
|
||||
.font(.callout)
|
||||
.foregroundColor(.gray)
|
||||
|
||||
} else if lastMessageDay < (currentDay - 1) && lastMessageDay > (currentDay - 5) {
|
||||
|
||||
Text(lastMessageTime, style: .date)
|
||||
|
||||
} else {
|
||||
|
||||
Text(lastMessageTime, style: .date)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
}
|
||||
.listRowSeparator(.hidden).frame(height: 5)
|
||||
|
||||
HStack(alignment: .top) {
|
||||
if user.messageList.count > 0 {
|
||||
|
||||
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
|
||||
|
||||
HStack {
|
||||
|
||||
Text(mostRecent!.messagePayload ?? "Empty Message")
|
||||
.frame(height: 60)
|
||||
.truncationMode(.tail)
|
||||
.foregroundColor(Color.gray)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
VStack {
|
||||
CircleText(text: user.shortName ?? "???", color: Color.blue)
|
||||
}
|
||||
.padding([.leading, .trailing])
|
||||
|
||||
VStack {
|
||||
|
||||
HStack {
|
||||
|
||||
VStack {
|
||||
Text(user.longName ?? "Unknown").font(.headline).fixedSize()
|
||||
}
|
||||
|
||||
VStack {
|
||||
|
||||
if lastMessageDay == currentDay {
|
||||
Text(lastMessageTime, style: .time )
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
} else if lastMessageDay == (currentDay - 1) {
|
||||
|
||||
Text("Yesterday")
|
||||
.font(.callout)
|
||||
.foregroundColor(.gray)
|
||||
|
||||
} else if lastMessageDay < (currentDay - 1) && lastMessageDay > (currentDay - 5) {
|
||||
|
||||
Text(lastMessageTime, style: .date)
|
||||
|
||||
} else {
|
||||
|
||||
Text(lastMessageTime, style: .date)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
}
|
||||
.listRowSeparator(.hidden).frame(height: 5)
|
||||
|
||||
HStack(alignment: .top) {
|
||||
|
||||
Text(mostRecent!.messagePayload ?? "Empty Message")
|
||||
.frame(height: 60)
|
||||
.truncationMode(.tail)
|
||||
.foregroundColor(Color.gray)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
.padding(.top)
|
||||
}
|
||||
} else {
|
||||
HStack {
|
||||
VStack {
|
||||
CircleText(text: user.shortName ?? "????", color: Color.blue)
|
||||
}
|
||||
.padding(.trailing)
|
||||
VStack {
|
||||
HStack {
|
||||
VStack {
|
||||
Text(user.longName ?? "Unknown").font(.headline).fixedSize()
|
||||
}
|
||||
VStack {
|
||||
Text(" ")
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
}
|
||||
.listRowSeparator(.hidden).frame(height: 5)
|
||||
}
|
||||
}.padding()
|
||||
}
|
||||
}
|
||||
.padding(.top)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
HStack {
|
||||
|
||||
VStack {
|
||||
|
||||
CircleText(text: user.shortName ?? "????", color: Color.blue)
|
||||
}
|
||||
.padding(.trailing)
|
||||
|
||||
VStack {
|
||||
|
||||
HStack {
|
||||
|
||||
VStack {
|
||||
|
||||
Text(user.longName ?? "Unknown").font(.headline).fixedSize()
|
||||
}
|
||||
|
||||
VStack {
|
||||
Text(" ")
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
}
|
||||
.listRowSeparator(.hidden).frame(height: 5)
|
||||
}
|
||||
}.padding()
|
||||
}
|
||||
}
|
||||
Section(header: Text("Private Channels")) {
|
||||
// Display Contacts for the rest of the non admin channels
|
||||
|
||||
}
|
||||
}
|
||||
.hidden()
|
||||
}
|
||||
.navigationTitle("Contacts")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
import SwiftUI
|
||||
import CoreData
|
||||
|
||||
struct UserMessageList: View {
|
||||
struct MessageList: View {
|
||||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
|
|
@ -43,49 +43,49 @@ struct UserMessageList: View {
|
|||
ScrollView {
|
||||
|
||||
if user.messageList.count > 0 {
|
||||
|
||||
ForEach( user.messageList ) { (message: MessageEntity) in
|
||||
|
||||
let currentUser: Bool = (bleManager.connectedPeripheral == nil) ? false : ((bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.num == message.fromUser?.num) ? true : false )
|
||||
|
||||
if message.toUser!.num == Int64(bleManager.broadcastNodeNum) || ((bleManager.connectedPeripheral) != nil && bleManager.connectedPeripheral.num == message.fromUser?.num) ? true : true {
|
||||
|
||||
if message.replyID > 0 {
|
||||
ForEach( user.messageList ) { (message: MessageEntity) in
|
||||
if user.num != userSettings.preferredNodeNum {
|
||||
let currentUser: Bool = (bleManager.connectedPeripheral == nil) ? false : ((bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.num == message.fromUser?.num) ? true : false )
|
||||
|
||||
if (message.toUser!.num == Int64(bleManager.broadcastNodeNum) || userSettings.preferredNodeNum == message.fromUser?.num) {
|
||||
|
||||
if message.replyID > 0 {
|
||||
|
||||
let messageReply = user.messageList.first(where: { $0.messageId == message.replyID })
|
||||
|
||||
HStack {
|
||||
|
||||
let messageReply = user.messageList.first(where: { $0.messageId == message.replyID })
|
||||
|
||||
HStack {
|
||||
|
||||
Text(messageReply?.messagePayload ?? "EMPTY MESSAGE").foregroundColor(.blue).font(.caption2)
|
||||
.padding(10)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 18)
|
||||
.stroke(Color.blue, lineWidth: 0.5)
|
||||
Text(messageReply?.messagePayload ?? "EMPTY MESSAGE").foregroundColor(.blue).font(.caption2)
|
||||
.padding(10)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 18)
|
||||
.stroke(Color.blue, lineWidth: 0.5)
|
||||
)
|
||||
Image(systemName: "arrowshape.turn.up.left.fill")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.imageScale(.large).foregroundColor(.blue)
|
||||
.padding(.trailing)
|
||||
}
|
||||
Image(systemName: "arrowshape.turn.up.left.fill")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.imageScale(.large).foregroundColor(.blue)
|
||||
.padding(.trailing)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HStack (alignment: .top) {
|
||||
|
||||
if currentUser { Spacer(minLength:50) }
|
||||
|
||||
if !currentUser {
|
||||
|
||||
CircleText(text: message.fromUser?.shortName ?? "????", color: currentUser ? .accentColor : Color(.darkGray), circleSize: 44, fontSize: 14)
|
||||
.padding(.all, 5)
|
||||
.offset(y: -5)
|
||||
}
|
||||
|
||||
|
||||
HStack (alignment: .top) {
|
||||
|
||||
if currentUser { Spacer(minLength:50) }
|
||||
VStack(alignment: currentUser ? .trailing : .leading) {
|
||||
|
||||
if !currentUser {
|
||||
|
||||
CircleText(text: message.fromUser?.shortName ?? "????", color: currentUser ? .accentColor : Color(.darkGray), circleSize: 44, fontSize: 14)
|
||||
.padding(.all, 5)
|
||||
.offset(y: -5)
|
||||
}
|
||||
|
||||
VStack(alignment: currentUser ? .trailing : .leading) {
|
||||
|
||||
Text(message.messagePayload ?? "EMPTY MESSAGE")
|
||||
Text(message.messagePayload ?? "EMPTY MESSAGE")
|
||||
.padding(10)
|
||||
|
||||
|
||||
.foregroundColor(.white)
|
||||
.background(currentUser ? Color.blue : Color(.darkGray))
|
||||
.cornerRadius(15)
|
||||
|
|
@ -150,7 +150,7 @@ struct UserMessageList: View {
|
|||
Image(uiImage: image!)
|
||||
}
|
||||
Button(action: {
|
||||
|
||||
|
||||
if bleManager.sendMessage(message: "‼️", toUserNum: user.num, isEmoji: true, replyID: message.messageId) {
|
||||
|
||||
print("Sent ‼️ Tapback")
|
||||
|
|
@ -178,7 +178,7 @@ struct UserMessageList: View {
|
|||
Image(uiImage: image!)
|
||||
}
|
||||
Button(action: {
|
||||
|
||||
|
||||
if bleManager.sendMessage(message: "💩", toUserNum: user.num, isEmoji: true, replyID: message.messageId) {
|
||||
|
||||
print("Sent 💩 Tapback")
|
||||
|
|
@ -195,7 +195,7 @@ struct UserMessageList: View {
|
|||
Button(action: {
|
||||
self.replyMessageId = message.messageId
|
||||
self.focusedField = .messageText
|
||||
|
||||
|
||||
print("I want to reply to \(message.messageId)")
|
||||
}) {
|
||||
Text("Reply")
|
||||
|
|
@ -212,14 +212,14 @@ struct UserMessageList: View {
|
|||
VStack {
|
||||
|
||||
let messageDate = Date(timeIntervalSince1970: TimeInterval(message.messageTimestamp))
|
||||
|
||||
|
||||
Text("Date \(messageDate, style: .date) \(messageDate.formattedDate(format: "h:mm:ss a"))").font(.caption2).foregroundColor(.gray)
|
||||
}
|
||||
|
||||
if currentUser && message.receivedACK {
|
||||
|
||||
VStack {
|
||||
|
||||
|
||||
Text("Received Ack \(message.receivedACK ? "✔️" : "")")
|
||||
}
|
||||
|
||||
|
|
@ -271,90 +271,91 @@ struct UserMessageList: View {
|
|||
Image(systemName: "trash")
|
||||
}
|
||||
}
|
||||
|
||||
let tapbacks = message.value(forKey: "tapbacks") as! [MessageEntity]
|
||||
|
||||
if tapbacks.count > 0 {
|
||||
|
||||
let tapbacks = message.value(forKey: "tapbacks") as! [MessageEntity]
|
||||
|
||||
if tapbacks.count > 0 {
|
||||
VStack (alignment: .trailing) {
|
||||
|
||||
VStack (alignment: .trailing) {
|
||||
|
||||
HStack {
|
||||
HStack {
|
||||
|
||||
ForEach( tapbacks ) { (tapback: MessageEntity) in
|
||||
|
||||
ForEach( tapbacks ) { (tapback: MessageEntity) in
|
||||
|
||||
VStack {
|
||||
|
||||
let image = tapback.messagePayload!.image(fontSize: 20)
|
||||
Image(uiImage: image!).font(.caption)
|
||||
Text("\(tapback.fromUser?.shortName ?? "????")")
|
||||
.font(.caption2)
|
||||
.foregroundColor(.gray)
|
||||
.fixedSize()
|
||||
.padding(.bottom, 1)
|
||||
}
|
||||
VStack {
|
||||
|
||||
let image = tapback.messagePayload!.image(fontSize: 20)
|
||||
Image(uiImage: image!).font(.caption)
|
||||
Text("\(tapback.fromUser?.shortName ?? "????")")
|
||||
.font(.caption2)
|
||||
.foregroundColor(.gray)
|
||||
.fixedSize()
|
||||
.padding(.bottom, 1)
|
||||
}
|
||||
}
|
||||
.padding(10)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 18)
|
||||
.stroke(Color.gray, lineWidth: 1)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
HStack {
|
||||
|
||||
if currentUser && message.receivedACK {
|
||||
|
||||
// Ack Received
|
||||
Text("Acknowledged").font(.caption2).foregroundColor(.gray)
|
||||
|
||||
} else if currentUser && message.ackError == 0 {
|
||||
|
||||
// Empty Error
|
||||
Text("Waiting to be acknowledged. . .").font(.caption2).foregroundColor(.orange)
|
||||
|
||||
} else if currentUser && message.ackError > 0 {
|
||||
|
||||
let ackErrorVal = RoutingError(rawValue: Int(message.ackError))
|
||||
Text("\(ackErrorVal?.display ?? "No Error" )").fixedSize(horizontal: false, vertical: true)
|
||||
.font(.caption2).foregroundColor(.red)
|
||||
}
|
||||
.padding(10)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 18)
|
||||
.stroke(Color.gray, lineWidth: 1)
|
||||
)
|
||||
}
|
||||
}
|
||||
.padding(.bottom)
|
||||
.id(user.messageList.firstIndex(of: message))
|
||||
if !currentUser {
|
||||
|
||||
HStack {
|
||||
|
||||
Spacer(minLength:50)
|
||||
if currentUser && message.receivedACK {
|
||||
|
||||
// Ack Received
|
||||
Text("Acknowledged").font(.caption2).foregroundColor(.gray)
|
||||
|
||||
} else if currentUser && message.ackError == 0 {
|
||||
|
||||
// Empty Error
|
||||
Text("Waiting to be acknowledged. . .").font(.caption2).foregroundColor(.orange)
|
||||
|
||||
} else if currentUser && message.ackError > 0 {
|
||||
|
||||
let ackErrorVal = RoutingError(rawValue: Int(message.ackError))
|
||||
Text("\(ackErrorVal?.display ?? "No Error" )").fixedSize(horizontal: false, vertical: true)
|
||||
.font(.caption2).foregroundColor(.red)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding([.leading, .trailing])
|
||||
.frame(maxWidth: .infinity)
|
||||
.id(message.messageId)
|
||||
.alert(isPresented: $showDeleteMessageAlert) {
|
||||
Alert(title: Text("Are you sure you want to delete this message?"), message: Text("This action is permanent."),
|
||||
primaryButton: .destructive(Text("Delete")) {
|
||||
.padding(.bottom)
|
||||
.id(user.messageList.firstIndex(of: message))
|
||||
if !currentUser {
|
||||
|
||||
Spacer(minLength:50)
|
||||
}
|
||||
}
|
||||
.padding([.leading, .trailing])
|
||||
.frame(maxWidth: .infinity)
|
||||
.id(message.messageId)
|
||||
.alert(isPresented: $showDeleteMessageAlert) {
|
||||
Alert(title: Text("Are you sure you want to delete this message?"), message: Text("This action is permanent."),
|
||||
primaryButton: .destructive(Text("Delete")) {
|
||||
print("OK button tapped")
|
||||
if deleteMessageId > 0 {
|
||||
|
||||
|
||||
let message = user.messageList.first(where: { $0.messageId == deleteMessageId })
|
||||
|
||||
|
||||
context.delete(message!)
|
||||
do {
|
||||
try context.save()
|
||||
|
||||
|
||||
deleteMessageId = 0
|
||||
|
||||
|
||||
} catch {
|
||||
print("Failed to delete message \(deleteMessageId)")
|
||||
print("Failed to delete message \(deleteMessageId)")
|
||||
}
|
||||
}
|
||||
},
|
||||
secondaryButton: .cancel()
|
||||
secondaryButton: .cancel()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.listRowSeparator(.hidden)
|
||||
}
|
||||
|
|
@ -5,7 +5,9 @@
|
|||
// Copyright(c) Garth Vander Houwen 7/7/22.
|
||||
//
|
||||
import SwiftUI
|
||||
#if canImport(Charts)
|
||||
import Charts
|
||||
#endif
|
||||
|
||||
struct DeviceMetricsLog: View {
|
||||
|
||||
|
|
@ -35,6 +37,8 @@ struct DeviceMetricsLog: View {
|
|||
|
||||
if data.count > 0 {
|
||||
|
||||
#if canImport(Charts)
|
||||
|
||||
GroupBox(label: Label("Battery Level Trend", systemImage: "battery.100")) {
|
||||
|
||||
Chart(data.array as! [TelemetryEntity], id: \.self) {
|
||||
|
|
@ -49,6 +53,8 @@ struct DeviceMetricsLog: View {
|
|||
}
|
||||
.frame(height: 150)
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
|
|
|
|||
|
|
@ -139,16 +139,16 @@ struct NodeList: View {
|
|||
self.initialLoad = false
|
||||
}
|
||||
}
|
||||
} detail: {
|
||||
} detail: {
|
||||
|
||||
if let node = selection {
|
||||
|
||||
if let node = selection {
|
||||
|
||||
NodeDetail(node:node)
|
||||
|
||||
} else {
|
||||
|
||||
Text("Select a node")
|
||||
}
|
||||
NodeDetail(node:node)
|
||||
|
||||
} else {
|
||||
|
||||
Text("Select a node")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ struct Settings: View {
|
|||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Share Channels QR Code")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
|
||||
NavigationLink {
|
||||
UserConfig(node: nodes.first(where: { $0.num == connectedNodeNum }))
|
||||
|
|
|
|||
|
|
@ -2,13 +2,12 @@
|
|||
// ShareChannel.swift
|
||||
// MeshtasticApple
|
||||
//
|
||||
// Created by Garth Vander Houwen on 4/8/22.
|
||||
// Copyright(c) Garth Vander Houwen 4/8/22.
|
||||
//
|
||||
import SwiftUI
|
||||
import CoreData
|
||||
import CoreImage.CIFilterBuiltins
|
||||
|
||||
|
||||
struct QrCodeImage {
|
||||
let context = CIContext()
|
||||
|
||||
|
|
@ -30,14 +29,10 @@ struct QrCodeImage {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
struct ShareChannels: View {
|
||||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
@EnvironmentObject var userSettings: UserSettings
|
||||
@State var initialLoad: Bool = true
|
||||
|
||||
@State var channelSet: ChannelSet = ChannelSet()
|
||||
@State var includeChannel0 = true
|
||||
@State var includeChannel1 = false
|
||||
|
|
@ -47,30 +42,20 @@ struct ShareChannels: View {
|
|||
@State var includeChannel5 = false
|
||||
@State var includeChannel6 = false
|
||||
@State var includeChannel7 = false
|
||||
|
||||
@State var isPresentingHelp = false
|
||||
|
||||
var node: NodeInfoEntity?
|
||||
|
||||
@State private var channelsUrl = "https://www.meshtastic.org/e/#"
|
||||
|
||||
var qrCodeImage = QrCodeImage()
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
GeometryReader { bounds in
|
||||
|
||||
let smallest = min(bounds.size.width, bounds.size.height)
|
||||
|
||||
ScrollView {
|
||||
|
||||
VStack {
|
||||
if node != nil {
|
||||
|
||||
if node != nil && node?.myInfo != nil {
|
||||
Grid(alignment: .top, horizontalSpacing: 2) {
|
||||
|
||||
GridRow {
|
||||
Spacer()
|
||||
Text("Include")
|
||||
|
|
@ -86,9 +71,7 @@ struct ShareChannels: View {
|
|||
.fontWeight(.bold)
|
||||
Spacer()
|
||||
}
|
||||
|
||||
ForEach(node!.myInfo!.channels?.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in
|
||||
|
||||
GridRow {
|
||||
Spacer()
|
||||
if channel.index == 0 {
|
||||
|
|
@ -155,47 +138,42 @@ struct ShareChannels: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
let qrImage = qrCodeImage.generateQRCode(from: channelsUrl)
|
||||
|
||||
let qrImage = qrCodeImage.generateQRCode(from: channelsUrl)
|
||||
VStack {
|
||||
|
||||
ShareLink("Share QR Code & Link",
|
||||
item: Image(uiImage: qrImage),
|
||||
subject: Text("Meshtastic Node \(node?.user?.shortName ?? "????") has shared channels with you"),
|
||||
message: Text(channelsUrl),
|
||||
preview: SharePreview("Meshtastic Node \(node?.user?.shortName ?? "????") has shared channels with you",
|
||||
image: Image(uiImage: qrImage))
|
||||
)
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
|
||||
Image(uiImage: qrImage)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(
|
||||
minWidth: smallest * 0.65,
|
||||
maxWidth: smallest * 0.65,
|
||||
minHeight: smallest * 0.65,
|
||||
maxHeight: smallest * 0.65,
|
||||
alignment: .top
|
||||
if node != nil {
|
||||
ShareLink("Share QR Code & Link",
|
||||
item: Image(uiImage: qrImage),
|
||||
subject: Text("Meshtastic Node \(node?.user?.shortName ?? "????") has shared channels with you"),
|
||||
message: Text(channelsUrl),
|
||||
preview: SharePreview("Meshtastic Node \(node?.user?.shortName ?? "????") has shared channels with you",
|
||||
image: Image(uiImage: qrImage))
|
||||
)
|
||||
|
||||
Button {
|
||||
|
||||
isPresentingHelp = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("Help Me!", systemImage: "lifepreserver")
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
Image(uiImage: qrImage)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(
|
||||
minWidth: smallest * 0.65,
|
||||
maxWidth: smallest * 0.65,
|
||||
minHeight: smallest * 0.65,
|
||||
maxHeight: smallest * 0.65,
|
||||
alignment: .top
|
||||
)
|
||||
Button {
|
||||
isPresentingHelp = true
|
||||
} label: {
|
||||
Label("Help Me!", systemImage: "lifepreserver")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.small)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.small)
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $isPresentingHelp) {
|
||||
|
||||
VStack {
|
||||
Text("Meshtastic Channels").font(.title)
|
||||
Text("A Meshtastic LoRa Mesh network can have up to 8 distinct channels.")
|
||||
|
|
@ -225,42 +203,20 @@ struct ShareChannels: View {
|
|||
.navigationTitle("Generate QR Code")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
self.initialLoad = false
|
||||
GenerateChannelSet()
|
||||
}
|
||||
}
|
||||
.onChange(of: includeChannel1) { includeCh1 in
|
||||
GenerateChannelSet()
|
||||
}
|
||||
.onChange(of: includeChannel2) { includeCh2 in
|
||||
GenerateChannelSet()
|
||||
}
|
||||
.onChange(of: includeChannel3) { includeCh3 in
|
||||
GenerateChannelSet()
|
||||
}
|
||||
.onChange(of: includeChannel4) { includeCh4 in
|
||||
GenerateChannelSet()
|
||||
}
|
||||
.onChange(of: includeChannel5) { includeCh5 in
|
||||
GenerateChannelSet()
|
||||
}
|
||||
.onChange(of: includeChannel6) { includeCh6 in
|
||||
GenerateChannelSet()
|
||||
}
|
||||
.onChange(of: includeChannel7) { includeCh7 in
|
||||
self.bleManager.context = context
|
||||
GenerateChannelSet()
|
||||
}
|
||||
.onChange(of: includeChannel1) { includeCh1 in GenerateChannelSet() }
|
||||
.onChange(of: includeChannel2) { includeCh2 in GenerateChannelSet() }
|
||||
.onChange(of: includeChannel3) { includeCh3 in GenerateChannelSet() }
|
||||
.onChange(of: includeChannel4) { includeCh4 in GenerateChannelSet() }
|
||||
.onChange(of: includeChannel5) { includeCh5 in GenerateChannelSet() }
|
||||
.onChange(of: includeChannel6) { includeCh6 in GenerateChannelSet() }
|
||||
.onChange(of: includeChannel7) { includeCh7 in GenerateChannelSet() }
|
||||
}
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
|
|
@ -268,34 +224,36 @@ struct ShareChannels: View {
|
|||
func GenerateChannelSet() {
|
||||
channelSet = ChannelSet()
|
||||
var loRaConfig = Config.LoRaConfig()
|
||||
loRaConfig.region = RegionCodes(rawValue: Int(node!.loRaConfig!.regionCode))!.protoEnumValue()
|
||||
loRaConfig.modemPreset = ModemPresets(rawValue: Int(node!.loRaConfig!.modemPreset))!.protoEnumValue()
|
||||
loRaConfig.bandwidth = UInt32(node!.loRaConfig!.bandwidth)
|
||||
loRaConfig.spreadFactor = UInt32(node!.loRaConfig!.spreadFactor)
|
||||
loRaConfig.codingRate = UInt32(node!.loRaConfig!.codingRate)
|
||||
loRaConfig.frequencyOffset = node!.loRaConfig!.frequencyOffset
|
||||
loRaConfig.hopLimit = UInt32(node!.loRaConfig!.hopLimit)
|
||||
loRaConfig.txEnabled = node!.loRaConfig!.txEnabled
|
||||
loRaConfig.txPower = node!.loRaConfig!.txPower
|
||||
loRaConfig.channelNum = UInt32(node!.loRaConfig!.channelNum)
|
||||
loRaConfig.region = RegionCodes(rawValue: Int(node?.loRaConfig?.regionCode ?? 0))!.protoEnumValue()
|
||||
loRaConfig.modemPreset = ModemPresets(rawValue: Int(node?.loRaConfig?.modemPreset ?? 0))!.protoEnumValue()
|
||||
loRaConfig.bandwidth = UInt32(node?.loRaConfig?.bandwidth ?? 0)
|
||||
loRaConfig.spreadFactor = UInt32(node?.loRaConfig?.spreadFactor ?? 0)
|
||||
loRaConfig.codingRate = UInt32(node?.loRaConfig?.codingRate ?? 0)
|
||||
loRaConfig.frequencyOffset = node?.loRaConfig?.frequencyOffset ?? 0
|
||||
loRaConfig.hopLimit = UInt32(node?.loRaConfig?.hopLimit ?? 3)
|
||||
loRaConfig.txEnabled = node?.loRaConfig?.txEnabled ?? false
|
||||
loRaConfig.txPower = node?.loRaConfig?.txPower ?? 0
|
||||
loRaConfig.channelNum = UInt32(node?.loRaConfig?.channelNum ?? 0)
|
||||
channelSet.loraConfig = loRaConfig
|
||||
for ch in node!.myInfo!.channels!.array as! [ChannelEntity] {
|
||||
if ch.role > 0 {
|
||||
|
||||
if ch.index == 0 && includeChannel0 || ch.index == 1 && includeChannel1 || ch.index == 2 && includeChannel2 || ch.index == 3 && includeChannel3 ||
|
||||
ch.index == 4 && includeChannel4 || ch.index == 5 && includeChannel5 || ch.index == 6 && includeChannel6 || ch.index == 7 && includeChannel7 {
|
||||
if node != nil {
|
||||
for ch in node!.myInfo!.channels!.array as! [ChannelEntity] {
|
||||
if ch.role > 0 {
|
||||
|
||||
var channelSettings = ChannelSettings()
|
||||
channelSettings.name = ch.name!
|
||||
channelSettings.psk = ch.psk!
|
||||
channelSettings.id = UInt32(ch.id)
|
||||
channelSettings.uplinkEnabled = ch.uplinkEnabled
|
||||
channelSettings.downlinkEnabled = ch.downlinkEnabled
|
||||
channelSet.settings.append(channelSettings)
|
||||
if ch.index == 0 && includeChannel0 || ch.index == 1 && includeChannel1 || ch.index == 2 && includeChannel2 || ch.index == 3 && includeChannel3 ||
|
||||
ch.index == 4 && includeChannel4 || ch.index == 5 && includeChannel5 || ch.index == 6 && includeChannel6 || ch.index == 7 && includeChannel7 {
|
||||
|
||||
var channelSettings = ChannelSettings()
|
||||
channelSettings.name = ch.name!
|
||||
channelSettings.psk = ch.psk!
|
||||
channelSettings.id = UInt32(ch.id)
|
||||
channelSettings.uplinkEnabled = ch.uplinkEnabled
|
||||
channelSettings.downlinkEnabled = ch.downlinkEnabled
|
||||
channelSet.settings.append(channelSettings)
|
||||
}
|
||||
}
|
||||
}
|
||||
let settingsString = try! channelSet.serializedData().base64EncodedString()
|
||||
channelsUrl = ("https://meshtastic.org/e/#" + settingsString.base64ToBase64url())
|
||||
}
|
||||
let settingsString = try! channelSet.serializedData().base64EncodedString()
|
||||
channelsUrl = ("https://meshtastic.org/e/#" + settingsString.base64ToBase64url())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue