diff --git a/Meshtastic/Views/Bluetooth/Connect.swift b/Meshtastic/Views/Bluetooth/Connect.swift index 8fcc31cb..42d23865 100644 --- a/Meshtastic/Views/Bluetooth/Connect.swift +++ b/Meshtastic/Views/Bluetooth/Connect.swift @@ -260,7 +260,7 @@ struct Connect: View { .navigationTitle("bluetooth") .navigationBarItems(leading: MeshtasticLogo(), trailing: ZStack { - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?", mqttProxyConnected: bleManager.mqttProxyConnected) + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?") }) } .sheet(isPresented: $invalidFirmwareVersion, onDismiss: didDismissSheet) { diff --git a/Meshtastic/Views/Helpers/ConnectedDevice.swift b/Meshtastic/Views/Helpers/ConnectedDevice.swift index 7e9d1852..6a33a970 100644 --- a/Meshtastic/Views/Helpers/ConnectedDevice.swift +++ b/Meshtastic/Views/Helpers/ConnectedDevice.swift @@ -5,56 +5,58 @@ A view draws the indicator used in the upper right corner for views using BLE import SwiftUI + struct ConnectedDevice: View { var bluetoothOn: Bool var deviceConnected: Bool var name: String - var mqttProxyEnabled: Bool = false - var mqttProxyConnected: Bool = false - var phoneOnly: Bool = false + + var mqttProxyConnected: Bool = false + var mqttUplinkEnabled: Bool = false + var mqttDownlinkEnabled: Bool = false + var mqttTopic: String = "" + var phoneOnly: Bool = false var body: some View { - HStack { - - if (phoneOnly && UIDevice.current.userInterfaceIdiom == .phone) || !phoneOnly { - if bluetoothOn { - if deviceConnected && (mqttProxyEnabled || mqttProxyConnected) { - if (mqttProxyConnected || mqttProxyEnabled) { - Image(systemName: "iphone.gen3.radiowaves.left.and.right.circle.fill") - .imageScale(.large) - .foregroundColor(mqttProxyConnected ? .green : .gray) - .symbolRenderingMode(.hierarchical) - } - } - if deviceConnected { - Image(systemName: "antenna.radiowaves.left.and.right.circle.fill") - .imageScale(.large) - .foregroundColor(.green) - .symbolRenderingMode(.hierarchical) - Text(name).font(name.isEmoji() ? .title : .callout).foregroundColor(.gray) - } else { - - Image(systemName: "antenna.radiowaves.left.and.right.slash") - .imageScale(.medium) - .foregroundColor(.red) - .symbolRenderingMode(.hierarchical) - } - } else { - Text("bluetooth.off").font(.subheadline).foregroundColor(.red) - } - } + if (phoneOnly && UIDevice.current.userInterfaceIdiom == .phone) || !phoneOnly { + if bluetoothOn { + if deviceConnected { + MQTTIcon(connected: mqttProxyConnected, uplink: mqttUplinkEnabled, downlink: mqttDownlinkEnabled, topic: mqttTopic) + Image(systemName: "antenna.radiowaves.left.and.right.circle.fill") + .imageScale(.large) + .foregroundColor(.green) + .symbolRenderingMode(.hierarchical) + Text(name).font(name.isEmoji() ? .title : .callout).foregroundColor(.gray) + } else { + Image(systemName: "antenna.radiowaves.left.and.right.slash") + .imageScale(.medium) + .foregroundColor(.red) + .symbolRenderingMode(.hierarchical) + } + } else { + Text("bluetooth.off").font(.subheadline).foregroundColor(.red) + } + } } } } + + + struct ConnectedDevice_Previews: PreviewProvider { static var previews: some View { - ConnectedDevice(bluetoothOn: true, deviceConnected: true, name: "MEMO", mqttProxyConnected: true) - .previewLayout(.fixed(width: 80, height: 70)) - - ConnectedDevice(bluetoothOn: true, deviceConnected: false, name: "86D4", mqttProxyConnected: false) - .previewLayout(.fixed(width: 80, height: 70)) - } - + VStack (alignment: .trailing) { + ConnectedDevice(bluetoothOn: true, deviceConnected: true, name: "MEMO", mqttProxyConnected: true) + ConnectedDevice(bluetoothOn: true, deviceConnected: true, name: "MEMO", mqttProxyConnected: false, mqttUplinkEnabled: true, mqttDownlinkEnabled: true) + ConnectedDevice(bluetoothOn: true, deviceConnected: true, name: "MEMO", mqttProxyConnected: true, mqttUplinkEnabled: true, mqttDownlinkEnabled: true, mqttTopic: "msh/US/2/e/#") + ConnectedDevice(bluetoothOn: true, deviceConnected: true, name: "MEMO", mqttProxyConnected: false, mqttUplinkEnabled: true, mqttDownlinkEnabled: false) + ConnectedDevice(bluetoothOn: true, deviceConnected: true, name: "MEMO", mqttProxyConnected: true, mqttUplinkEnabled: true, mqttDownlinkEnabled: false) + ConnectedDevice(bluetoothOn: true, deviceConnected: true, name: "MEMO", mqttProxyConnected: false, mqttUplinkEnabled: false, mqttDownlinkEnabled: true) + ConnectedDevice(bluetoothOn: true, deviceConnected: true, name: "MEMO", mqttProxyConnected: true, mqttUplinkEnabled: false, mqttDownlinkEnabled: true) + ConnectedDevice(bluetoothOn: true, deviceConnected: true, name: "MEMO", mqttProxyConnected: true) + ConnectedDevice(bluetoothOn: true, deviceConnected: false, name: "MEMO", mqttProxyConnected: false) + }.previewLayout(.fixed(width: 150, height: 275)) + } } diff --git a/Meshtastic/Views/Helpers/MQTTIcon.swift b/Meshtastic/Views/Helpers/MQTTIcon.swift new file mode 100644 index 00000000..f67887e0 --- /dev/null +++ b/Meshtastic/Views/Helpers/MQTTIcon.swift @@ -0,0 +1,54 @@ +// +// MQTTIcon.swift +// Meshtastic +// +// Created by Matthew Davies on 4/1/24. +// + +import Foundation +import SwiftUI + +struct MQTTIcon: View { + var connected: Bool = false + var uplink: Bool = false + var downlink: Bool = false + var topic: String = "" + + @State var isPopoverOpen = false + + var body: some View { + Button( action: { + if(topic.length > 0) {self.isPopoverOpen.toggle()} + } ) { + // the last one defaults to just showing up/down if it isn't specified b/c on the mqtt config screen, there's no information about uplink/downlink and no good alternative icon + Image(systemName: uplink && downlink ? "arrow.up.arrow.down.circle.fill" : uplink ? "arrow.up.circle.fill" : downlink ? "arrow.down.circle.fill" : "arrow.up.arrow.down.circle.fill") + .imageScale(.large) + .foregroundColor(connected ? .green : .gray) + .symbolRenderingMode(.hierarchical) + }.popover(isPresented: self.$isPopoverOpen, content: { + VStack(spacing: 0.5) { + Text("Subscribed to topic: " + topic) + .padding(20) + Button("Close", action: { self.isPopoverOpen = false }).padding([.bottom], 20) + } + }) + } +} + +struct MQTTIcon_Previews: PreviewProvider { + static var previews: some View { + VStack { + MQTTIcon(connected: true) + MQTTIcon(connected: false) + + MQTTIcon(connected: true, uplink: true, downlink: true) + MQTTIcon(connected: false, uplink: true, downlink: true) + + MQTTIcon(connected: true, uplink: true) + MQTTIcon(connected: false, uplink: true) + + MQTTIcon(connected: true, downlink: true) + MQTTIcon(connected: false, downlink: true) + }.previewLayout(.fixed(width: 25, height: 220)) + } +} diff --git a/Meshtastic/Views/Messages/ChannelMessageList.swift b/Meshtastic/Views/Messages/ChannelMessageList.swift index 234d705a..9017951f 100644 --- a/Meshtastic/Views/Messages/ChannelMessageList.swift +++ b/Meshtastic/Views/Messages/ChannelMessageList.swift @@ -157,8 +157,12 @@ struct ChannelMessageList: View { bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?", - mqttProxyEnabled: channel.uplinkEnabled || channel.downlinkEnabled, - mqttProxyConnected: channel.uplinkEnabled || channel.downlinkEnabled ? bleManager.mqttProxyConnected : false + + // mqttProxyConnected defaults to false, so if it's not enabled it will still be false + mqttProxyConnected: bleManager.mqttProxyConnected, + mqttUplinkEnabled: channel.uplinkEnabled, + mqttDownlinkEnabled: channel.downlinkEnabled, + mqttTopic: bleManager.mqttManager.topic ) } } diff --git a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift index 9079d530..a6931aff 100644 --- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift @@ -272,7 +272,7 @@ struct MQTTConfig: View { .navigationTitle("mqtt.config") .navigationBarItems(trailing: ZStack { - ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?", mqttProxyEnabled: self.enabled, mqttProxyConnected: bleManager.mqttProxyConnected) + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?", mqttProxyConnected: bleManager.mqttProxyConnected) }) .onChange(of: address) { newAddress in if node != nil && node?.mqttConfig != nil {