diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 8f38858b..7482f8fe 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -456,6 +456,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate let binaryData: Data = try! toRadio.serializedData() connectedPeripheral!.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse) // Either Read the config complete value or from num notify value + guard connectedPeripheral != nil else { return } connectedPeripheral!.peripheral.readValue(for: FROMRADIO_characteristic) } } diff --git a/Meshtastic/Views/Messages/ChannelList.swift b/Meshtastic/Views/Messages/ChannelList.swift index a956f8ff..e6c8f99d 100644 --- a/Meshtastic/Views/Messages/ChannelList.swift +++ b/Meshtastic/Views/Messages/ChannelList.swift @@ -26,119 +26,116 @@ struct ChannelList: View { let dateFormatString = (localeDateFormat ?? "MM/dd/YY") VStack { - List { - // Display Contacts for the rest of the non admin channels - if node != nil && node!.myInfo != nil && node!.myInfo!.channels != nil { - ForEach(node!.myInfo!.channels!.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in - if channel.name?.lowercased() ?? "" != "admin" && channel.name?.lowercased() ?? "" != "gpio" && channel.name?.lowercased() ?? "" != "serial" { + // Display Contacts for the rest of the non admin channels + if node != nil && node!.myInfo != nil && node!.myInfo!.channels != nil { + List(node!.myInfo!.channels!.array as! [ChannelEntity], id: \.self, selection: $channelSelection) { (channel: ChannelEntity) in + if channel.name?.lowercased() ?? "" != "admin" && channel.name?.lowercased() ?? "" != "gpio" && channel.name?.lowercased() ?? "" != "serial" { - NavigationLink(destination: ChannelMessageList(myInfo: node!.myInfo!, channel: channel)) { + NavigationLink(destination: ChannelMessageList(myInfo: node!.myInfo!, channel: channel)) { - let mostRecent = channel.allPrivateMessages.last(where: { $0.channel == channel.index }) - let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64((mostRecent?.messageTimestamp ?? 0 )))) - let lastMessageDay = Calendar.current.dateComponents([.day], from: lastMessageTime).day ?? 0 - let currentDay = Calendar.current.dateComponents([.day], from: Date()).day ?? 0 + let mostRecent = channel.allPrivateMessages.last(where: { $0.channel == channel.index }) + let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64((mostRecent?.messageTimestamp ?? 0 )))) + let lastMessageDay = Calendar.current.dateComponents([.day], from: lastMessageTime).day ?? 0 + let currentDay = Calendar.current.dateComponents([.day], from: Date()).day ?? 0 - - ZStack { - Image(systemName: "circle.fill") - .opacity(channel.unreadMessages > 0 ? 1 : 0) - .font(.system(size: 10)) - .foregroundColor(.accentColor) - .brightness(0.2) - } - CircleText(text: String(channel.index), color: .accentColor) + ZStack { + Image(systemName: "circle.fill") + .opacity(channel.unreadMessages > 0 ? 1 : 0) + .font(.system(size: 10)) + .foregroundColor(.accentColor) .brightness(0.2) - - VStack(alignment: .leading){ - HStack{ - if channel.name?.isEmpty ?? false { - if channel.role == 1 { - Text(String("PrimaryChannel").camelCaseToWords()) - .font(.headline) - } else { - Text(String("Channel \(channel.index)").camelCaseToWords()) - .font(.headline) - } + } + CircleText(text: String(channel.index), color: .accentColor) + .brightness(0.2) + + VStack(alignment: .leading){ + HStack{ + if channel.name?.isEmpty ?? false { + if channel.role == 1 { + Text(String("PrimaryChannel").camelCaseToWords()) + .font(.headline) } else { - Text(String(channel.name ?? "Channel \(channel.index)").camelCaseToWords()) + Text(String("Channel \(channel.index)").camelCaseToWords()) .font(.headline) } - - Spacer() - - if channel.allPrivateMessages.count > 0 { - - if lastMessageDay == currentDay { - Text(lastMessageTime, style: .time ) - .font(.footnote) - .foregroundColor(.secondary) - } else if lastMessageDay == (currentDay - 1) { - Text("Yesterday") - .font(.footnote) - .foregroundColor(.secondary) - } else if lastMessageDay < (currentDay - 1) && lastMessageDay > (currentDay - 5) { - Text(lastMessageTime.formattedDate(format: dateFormatString)) - .font(.footnote) - .foregroundColor(.secondary) - } else if lastMessageDay < (currentDay - 1800) { - Text(lastMessageTime.formattedDate(format: dateFormatString)) - .font(.footnote) - .foregroundColor(.secondary) - } - } -// Image(systemName: "chevron.forward") -// .font(.caption) -// .foregroundColor(.secondary) + } else { + Text(String(channel.name ?? "Channel \(channel.index)").camelCaseToWords()) + .font(.headline) } + Spacer() + if channel.allPrivateMessages.count > 0 { - HStack(alignment: .top) { - Text("\(mostRecent != nil ? mostRecent!.messagePayload! : " ")") - //.font(.system(size: 16)) + + if lastMessageDay == currentDay { + Text(lastMessageTime, style: .time ) + .font(.footnote) + .foregroundColor(.secondary) + } else if lastMessageDay == (currentDay - 1) { + Text("Yesterday") + .font(.footnote) + .foregroundColor(.secondary) + } else if lastMessageDay < (currentDay - 1) && lastMessageDay > (currentDay - 5) { + Text(lastMessageTime.formattedDate(format: dateFormatString)) + .font(.footnote) + .foregroundColor(.secondary) + } else if lastMessageDay < (currentDay - 1800) { + Text(lastMessageTime.formattedDate(format: dateFormatString)) .font(.footnote) .foregroundColor(.secondary) } } +// Image(systemName: "chevron.forward") +// .font(.caption) +// .foregroundColor(.secondary) } - } - .frame(height: 62) - .contextMenu { + if channel.allPrivateMessages.count > 0 { - Button(role: .destructive) { - isPresentingDeleteChannelMessagesConfirm = true - channelSelection = channel - } label: { - Label("Delete Messages", systemImage: "trash") + HStack(alignment: .top) { + Text("\(mostRecent != nil ? mostRecent!.messagePayload! : " ")") + //.font(.system(size: 16)) + .font(.footnote) + .foregroundColor(.secondary) } } } - .confirmationDialog( - "This conversation will be deleted.", - isPresented: $isPresentingDeleteChannelMessagesConfirm, - titleVisibility: .visible - ) { + } + .frame(height: 62) + .contextMenu { + if channel.allPrivateMessages.count > 0 { Button(role: .destructive) { - deleteChannelMessages(channel: channelSelection!, context: context) - context.refresh(node!.myInfo!, mergeChanges: true) - UIApplication.shared.applicationIconBadgeNumber = appState.unreadChannelMessages + appState.unreadDirectMessages - channelSelection = nil + isPresentingDeleteChannelMessagesConfirm = true + channelSelection = channel } label: { - Text("delete") - } - } - .onAppear { - if self.bleManager.context == nil { - self.bleManager.context = context + Label("Delete Messages", systemImage: "trash") } } } + .confirmationDialog( + "This conversation will be deleted.", + isPresented: $isPresentingDeleteChannelMessagesConfirm, + titleVisibility: .visible + ) { + Button(role: .destructive) { + deleteChannelMessages(channel: channelSelection!, context: context) + context.refresh(node!.myInfo!, mergeChanges: true) + UIApplication.shared.applicationIconBadgeNumber = appState.unreadChannelMessages + appState.unreadDirectMessages + channelSelection = nil + } label: { + Text("delete") + } + } + .onAppear { + if self.bleManager.context == nil { + self.bleManager.context = context + } + } } - .padding([.top, .bottom]) } + .padding([.top, .bottom]) + .listStyle(.plain) } - .listStyle(.plain) - .navigationTitle("channels") } + .navigationTitle("channels") } } diff --git a/Meshtastic/Views/Messages/ChannelMessageList.swift b/Meshtastic/Views/Messages/ChannelMessageList.swift index aa1b1a20..e5795ce9 100644 --- a/Meshtastic/Views/Messages/ChannelMessageList.swift +++ b/Meshtastic/Views/Messages/ChannelMessageList.swift @@ -24,8 +24,8 @@ struct ChannelMessageList: View { var maxbytes = 228 @FocusState var focusedField: Field? - @StateObject var myInfo: MyInfoEntity - @StateObject var channel: ChannelEntity + @ObservedObject var myInfo: MyInfoEntity + @ObservedObject var channel: ChannelEntity @State var showDeleteMessageAlert = false @State private var deleteMessageId: Int64 = 0 @State private var replyMessageId: Int64 = 0