diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 7e0e3951..01c0c90f 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -191,9 +191,6 @@ }, "8" : { - }, - "10% Airtime" : { - }, "25" : { @@ -679,7 +676,7 @@ "Airtime" : { }, - "AirTm" : { + "Airtime %@%%" : { }, "Alert" : { @@ -1427,9 +1424,6 @@ }, "Barometric Pressure" : { - }, - "Batt" : { - }, "Battery Level %" : { @@ -2791,6 +2785,9 @@ }, "Channel Role" : { + }, + "Channel Utilization %@%% " : { + }, "channel.role.disabled" : { "extractionState" : "migrated", @@ -3090,9 +3087,6 @@ }, "CHG" : { - }, - "ChUtil" : { - }, "Clear" : { @@ -22291,9 +22285,6 @@ }, "Via Mqtt" : { - }, - "Volt" : { - }, "voltage" : { "localizations" : { @@ -22352,6 +22343,9 @@ } } } + }, + "Volts %@ " : { + }, "waiting" : { "localizations" : { diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 6c090d2f..49bf08ef 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -68,6 +68,7 @@ DD3501892852FC3B000FC853 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3501882852FC3B000FC853 /* Settings.swift */; }; DD354FD92BD96A0B0061A25F /* IAQScale.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD354FD82BD96A0B0061A25F /* IAQScale.swift */; }; DD3619152B1EF9F900C41C8C /* LocationsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3619142B1EF9F900C41C8C /* LocationsHandler.swift */; }; + DD3CC24C2C498D6C001BD3A2 /* BatteryCompact.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3CC24B2C498D6C001BD3A2 /* BatteryCompact.swift */; }; DD3CC6B528E33FD100FA9159 /* ShareChannels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3CC6B428E33FD100FA9159 /* ShareChannels.swift */; }; DD3CC6BC28E366DF00FA9159 /* Meshtastic.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DD3CC6BA28E366DF00FA9159 /* Meshtastic.xcdatamodeld */; }; DD3CC6BE28E4CD9800FA9159 /* BatteryGauge.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3CC6BD28E4CD9800FA9159 /* BatteryGauge.swift */; }; @@ -248,12 +249,12 @@ 2519268F2C3CB44900249DF5 /* ClientHistoryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientHistoryButton.swift; sourceTree = ""; }; 251926912C3CB52300249DF5 /* DeleteNodeButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteNodeButton.swift; sourceTree = ""; }; 25AECD4E2C2F723200862C8E /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = ""; }; + 25C49D8F2C471AEA0024FBD1 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; 25F5D5BD2C3F6D87008036E3 /* NavigationState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationState.swift; sourceTree = ""; }; 25F5D5BF2C3F6DA6008036E3 /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; 25F5D5C12C3F6E4B008036E3 /* AppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = ""; }; 25F5D5C72C4375A8008036E3 /* MeshtasticTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MeshtasticTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 25F5D5D02C4375DF008036E3 /* RouterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterTests.swift; sourceTree = ""; }; - 25C49D8F2C471AEA0024FBD1 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; 6D825E612C34786C008DBEE4 /* CommonRegex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonRegex.swift; sourceTree = ""; }; 6DA39D8D2A92DC52007E311C /* MeshtasticAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticAppDelegate.swift; sourceTree = ""; }; 6DEDA5592A957B8E00321D2E /* DetectionSensorLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetectionSensorLog.swift; sourceTree = ""; }; @@ -307,6 +308,7 @@ DD3619132B1EE20700C41C8C /* MeshtasticDataModelV21.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV21.xcdatamodel; sourceTree = ""; }; DD3619142B1EF9F900C41C8C /* LocationsHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationsHandler.swift; sourceTree = ""; }; DD398EBD2B93F640002B4C51 /* MeshtasticDataModelV 29.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 29.xcdatamodel"; sourceTree = ""; }; + DD3CC24B2C498D6C001BD3A2 /* BatteryCompact.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryCompact.swift; sourceTree = ""; }; DD3CC6B428E33FD100FA9159 /* ShareChannels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareChannels.swift; sourceTree = ""; }; DD3CC6BB28E366DF00FA9159 /* MeshtasticDataModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModel.xcdatamodel; sourceTree = ""; }; DD3CC6BD28E4CD9800FA9159 /* BatteryGauge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryGauge.swift; sourceTree = ""; }; @@ -882,6 +884,7 @@ isa = PBXGroup; children = ( DD3CC6BD28E4CD9800FA9159 /* BatteryGauge.swift */, + DD3CC24B2C498D6C001BD3A2 /* BatteryCompact.swift */, DDB75A222A13CDA9006ED576 /* BatteryLevelCompact.swift */, DD457187293C7E63000C49FB /* BLESignalStrengthIndicator.swift */, DD47E3D526F17ED900029299 /* CircleText.swift */, @@ -1320,6 +1323,7 @@ DDB75A112A059258006ED576 /* Url.swift in Sources */, DDAD49ED2AFB39DC00B4425D /* MeshMap.swift in Sources */, DD8169FB271F1F3A00F4AB02 /* MeshLog.swift in Sources */, + DD3CC24C2C498D6C001BD3A2 /* BatteryCompact.swift in Sources */, DD1B8F402B35E2F10022AABC /* GPSStatus.swift in Sources */, DD8ED9C52898D51F00B3B0AB /* NetworkConfig.swift in Sources */, DDC3B274283F411B00AC321C /* LastHeardText.swift in Sources */, diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index e6a7f0cb..5d6cceb8 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -1061,7 +1061,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate } } } catch { - + Logger.data.error("💥 Send message failure \(self.connectedPeripheral.num.toHex(), privacy: .public) to \(toUserNum.toHex(), privacy: .public)") } } return success diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index ab3cdf47..3fac0312 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -263,7 +263,7 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext) } if fetchedNode[0].user == nil { let newUser = createUser(num: Int64(truncatingIfNeeded: packet.from), context: context) - fetchedNode[0].user! = newUser + fetchedNode[0].user? = newUser } do { diff --git a/Meshtastic/Views/Helpers/BatteryCompact.swift b/Meshtastic/Views/Helpers/BatteryCompact.swift new file mode 100644 index 00000000..28f62a57 --- /dev/null +++ b/Meshtastic/Views/Helpers/BatteryCompact.swift @@ -0,0 +1,68 @@ +// +// BatteryCompact.swift +// Meshtastic +// +// Created by Garth Vander Houwen on 7/18/24. +// +import SwiftUI + +struct BatteryCompact: View { + @State var batteryLevel: Int32 + var font: Font + var iconFont: Font + var color: Color + + var body: some View { + HStack(alignment: .center, spacing: 0) { + if batteryLevel == 100 { + Image(systemName: "battery.100.bolt") + .font(iconFont) + .foregroundColor(color) + .symbolRenderingMode(.multicolor) + } else if batteryLevel < 100 && batteryLevel > 74 { + Image(systemName: "battery.75") + .font(iconFont) + .foregroundColor(color) + .symbolRenderingMode(.multicolor) + } else if batteryLevel < 75 && batteryLevel > 49 { + Image(systemName: "battery.50") + .font(iconFont) + .foregroundColor(color) + .symbolRenderingMode(.multicolor) + } else if batteryLevel < 50 && batteryLevel > 14 { + Image(systemName: "battery.25") + .font(iconFont) + .foregroundColor(color) + .symbolRenderingMode(.multicolor) + } else if batteryLevel < 15 && batteryLevel > 0 { + Image(systemName: "battery.0") + .font(iconFont) + .foregroundColor(color) + .symbolRenderingMode(.multicolor) + } else if batteryLevel == 0 { + Image(systemName: "battery.0") + .font(iconFont) + .foregroundColor(.red) + .symbolRenderingMode(.multicolor) + } else if batteryLevel > 100 { + Image(systemName: "powerplug") + .font(iconFont) + .foregroundColor(color) + .symbolRenderingMode(.multicolor) + } + if batteryLevel > 100 { + Text("PWD") + .foregroundStyle(.secondary) + .font(font) + } else if batteryLevel == 100 { + Text("CHG") + .foregroundStyle(.secondary) + .font(font) + } else { + Text("\(batteryLevel)%") + .foregroundStyle(.secondary) + .font(font) + } + } + } +} diff --git a/Meshtastic/Views/Helpers/BatteryLevelCompact.swift b/Meshtastic/Views/Helpers/BatteryLevelCompact.swift index 7bb2542c..e1354e23 100644 --- a/Meshtastic/Views/Helpers/BatteryLevelCompact.swift +++ b/Meshtastic/Views/Helpers/BatteryLevelCompact.swift @@ -19,61 +19,7 @@ struct BatteryLevelCompact: View { let mostRecent = deviceMetrics?.lastObject as? TelemetryEntity let batteryLevel = mostRecent?.batteryLevel ?? 0 if deviceMetrics?.count ?? 0 > 0 { - HStack(alignment: .center, spacing: 0) { - if batteryLevel == 100 { - Image(systemName: "battery.100.bolt") - .font(iconFont) - .foregroundColor(color) - .symbolRenderingMode(.hierarchical) - } else if batteryLevel < 100 && batteryLevel > 74 { - - Image(systemName: "battery.75") - .font(iconFont) - .foregroundColor(color) - .symbolRenderingMode(.hierarchical) - } else if batteryLevel < 75 && batteryLevel > 49 { - - Image(systemName: "battery.50") - .font(iconFont) - .foregroundColor(color) - .symbolRenderingMode(.hierarchical) - } else if batteryLevel < 50 && batteryLevel > 14 { - - Image(systemName: "battery.25") - .font(iconFont) - .foregroundColor(color) - .symbolRenderingMode(.hierarchical) - } else if batteryLevel < 15 && batteryLevel > 0 { - - Image(systemName: "battery.0") - .font(iconFont) - .foregroundColor(color) - .symbolRenderingMode(.hierarchical) - } else if batteryLevel == 0 { - Image(systemName: "battery.0") - .font(iconFont) - .foregroundColor(.red) - .symbolRenderingMode(.hierarchical) - } else if batteryLevel > 100 { - Image(systemName: "powerplug") - .font(iconFont) - .foregroundColor(color) - .symbolRenderingMode(.hierarchical) - } - if batteryLevel > 100 { - Text("PWD") - .foregroundStyle(.gray) - .font(font) - } else if batteryLevel == 100 { - Text("CHG") - .foregroundStyle(.gray) - .font(font) - } else { - Text("\(batteryLevel)%") - .foregroundStyle(.gray) - .font(font) - } - } + BatteryCompact(batteryLevel: batteryLevel, font: font, iconFont: iconFont, color: color) } } } diff --git a/Meshtastic/Views/Helpers/MQTTIcon.swift b/Meshtastic/Views/Helpers/MQTTIcon.swift index 4cd615be..79821dd1 100644 --- a/Meshtastic/Views/Helpers/MQTTIcon.swift +++ b/Meshtastic/Views/Helpers/MQTTIcon.swift @@ -23,7 +23,7 @@ struct MQTTIcon: View { // 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) + .foregroundColor(connected ? .green : .secondary) .symbolRenderingMode(.hierarchical) }.popover(isPresented: self.$isPopoverOpen, arrowEdge: .bottom, content: { VStack(spacing: 0.5) { diff --git a/Meshtastic/Views/Nodes/DeviceMetricsLog.swift b/Meshtastic/Views/Nodes/DeviceMetricsLog.swift index bbabf31e..51a68a49 100644 --- a/Meshtastic/Views/Nodes/DeviceMetricsLog.swift +++ b/Meshtastic/Views/Nodes/DeviceMetricsLog.swift @@ -12,6 +12,7 @@ struct DeviceMetricsLog: View { @Environment(\.managedObjectContext) var context @EnvironmentObject var bleManager: BLEManager + private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } @State private var isPresentingClearLogConfirm: Bool = false @State var isExporting = false @@ -21,6 +22,8 @@ struct DeviceMetricsLog: View { @State private var airtimeChartColor: Color = .yellow @State private var channelUtilizationChartColor: Color = .green @ObservedObject var node: NodeInfoEntity + @State private var sortOrder = [KeyPathComparator(\TelemetryEntity.time, order: .reverse)] + @State private var selection: TelemetryEntity.ID? var body: some View { VStack { @@ -32,7 +35,6 @@ struct DeviceMetricsLog: View { .sorted { $0.time! < $1.time! } if chartData.count > 0 { GroupBox(label: Label("\(deviceMetrics.count) Readings Total", systemImage: "chart.xyaxis.line")) { - Chart { ForEach(chartData, id: \.self) { point in Plot { @@ -57,14 +59,9 @@ struct DeviceMetricsLog: View { .accessibilityValue("X: \(point.time!), Y: \(point.channelUtilization)") .foregroundStyle(channelUtilizationChartColor) - RuleMark(y: .value("10% Airtime", 10)) - .lineStyle(StrokeStyle(lineWidth: 1, dash: [5, 10])) - .foregroundStyle(.yellow) - RuleMark(y: .value("Network Status Orange", 25)) .lineStyle(StrokeStyle(lineWidth: 1, dash: [5, 10])) .foregroundStyle(.orange) - RuleMark(y: .value("Network Status Red", 50)) .lineStyle(StrokeStyle(lineWidth: 1, dash: [5, 10])) .foregroundStyle(.red) @@ -87,20 +84,46 @@ struct DeviceMetricsLog: View { .chartXAxis(.automatic) .chartYScale(domain: 0...100) .chartForegroundStyleScale([ - "Battery Level": batteryChartColor, + idiom == .phone ? "Battery" : "Battery Level": batteryChartColor, "Channel Utilization": channelUtilizationChartColor, "Airtime": airtimeChartColor ]) .chartLegend(position: .automatic, alignment: .bottom) } - .frame(minHeight: 250) + .frame(minHeight: 240) } let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMdjmma", options: 0, locale: Locale.current) let dateFormatString = (localeDateFormat ?? "M/d/YY j:mma").replacingOccurrences(of: ",", with: "") - if UIScreen.main.bounds.size.width > 768 && (UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac) { - // Add a table for mac and ipad - // Table(Array(deviceMetrics),id: \.self) { - Table(deviceMetrics) { + if idiom == .phone { + /// Single Cell Compact display for phones + Table(deviceMetrics, selection: $selection, sortOrder: $sortOrder) { + TableColumn("battery.level") { dm in + HStack { + Text(dm.time?.formattedDate(format: dateFormatString) ?? "unknown.age".localized) + .font(.caption) + .fontWeight(.semibold) + Spacer() + Image(systemName: "bolt") + .font(.caption) + .symbolRenderingMode(.multicolor) + Text("Volts \(String(format: "%.2f", dm.voltage)) ") + .font(.caption2) + BatteryCompact(batteryLevel: dm.batteryLevel, font: .caption, iconFont: .callout, color: .accentColor) + } + HStack { + Text("Channel Utilization \(String(format: "%.2f", dm.channelUtilization))% ") + .foregroundColor(dm.channelUtilization < 25 ? .green : (dm.channelUtilization > 50 ? .red : .orange)) + Text("Airtime \(String(format: "%.2f", dm.airUtilTx))%") + .foregroundColor(.secondary) + Spacer() + } + .font(.caption) + } + .width(ideal: 200, max: .infinity) + } + } else { + /// Multi Column table for ipads and mac + Table(deviceMetrics, selection: $selection, sortOrder: $sortOrder) { TableColumn("battery.level") { dm in if dm.batteryLevel > 100 { Text("Powered") @@ -113,6 +136,7 @@ struct DeviceMetricsLog: View { } TableColumn("channel.utilization") { dm in Text("\(String(format: "%.2f", dm.channelUtilization))%") + .foregroundColor(dm.channelUtilization < 25 ? .green : (dm.channelUtilization > 50 ? .red : .orange)) } TableColumn("airtime") { dm in Text("\(String(format: "%.2f", dm.airUtilTx))%") @@ -123,61 +147,12 @@ struct DeviceMetricsLog: View { let components = (now.. 100 { - Text("PWD") - .font(.caption) - } else { - Text("\(String(dm.batteryLevel))%") - .font(.caption) - } - Text(String(dm.voltage)) - .font(.caption) - Text("\(String(format: "%.2f", dm.channelUtilization))%") - .font(.caption) - Text("\(String(format: "%.2f", dm.airUtilTx))%") - .font(.caption) - Text(dm.time?.formattedDate(format: dateFormatString) ?? "unknown.age".localized) - .font(.caption) - } - } - } - .padding(.leading, 15) - .padding(.trailing, 5) - } } HStack { Button(role: .destructive) { @@ -187,7 +162,7 @@ struct DeviceMetricsLog: View { } .buttonStyle(.bordered) .buttonBorderShape(.capsule) - .controlSize(.large) + .controlSize(idiom == .phone ? .regular : .large) .padding(.bottom) .padding(.leading) .confirmationDialog( @@ -212,7 +187,7 @@ struct DeviceMetricsLog: View { } .buttonStyle(.bordered) .buttonBorderShape(.capsule) - .controlSize(.large) + .controlSize(idiom == .phone ? .regular : .large) .padding(.bottom) .padding(.trailing) } diff --git a/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift b/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift index 172795e4..a68a63cd 100644 --- a/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift +++ b/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift @@ -35,7 +35,7 @@ struct NodeListItem: View { if node.favorite { Spacer() Image(systemName: "star.fill") - .foregroundColor(.yellow) + .symbolRenderingMode(.multicolor) } } if connected { @@ -75,11 +75,11 @@ struct NodeListItem: View { HStack { Image(systemName: "envelope.arrow.triangle.branch") .font(.callout) - .symbolRenderingMode(.hierarchical) + .symbolRenderingMode(.multicolor) .frame(width: 30) Text("storeforward".localized) .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) - .foregroundColor(.gray) + .foregroundColor(.secondary) } } @@ -94,7 +94,7 @@ struct NodeListItem: View { let metersAway = nodeCoord.distance(from: myCoord) Image(systemName: "lines.measurement.horizontal") .font(.callout) - .symbolRenderingMode(.hierarchical) + .symbolRenderingMode(.multicolor) .frame(width: 30) DistanceText(meters: metersAway) .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) @@ -109,11 +109,11 @@ struct NodeListItem: View { let metersAway = nodeCoord.distance(from: myCoord) Image(systemName: "lines.measurement.horizontal") .font(.callout) - .symbolRenderingMode(.hierarchical) + .symbolRenderingMode(.multicolor) .frame(width: 30) DistanceText(meters: metersAway) .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) - .foregroundColor(.gray) + .foregroundColor(.secondary) } } } @@ -124,18 +124,17 @@ struct NodeListItem: View { HStack { Image(systemName: "\(node.channel).circle.fill") .font(.title2) - .symbolRenderingMode(.hierarchical) + .symbolRenderingMode(.multicolor) .frame(width: 30) - .foregroundColor(.accentColor) Text("Channel") - .foregroundColor(.gray) + .foregroundColor(.secondary) .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) } } if node.viaMqtt && connectedNode != node.num { Image(systemName: "dot.radiowaves.up.forward") - .symbolRenderingMode(.hierarchical) + .symbolRenderingMode(.multicolor) .font(.callout) .frame(width: 30) Text("MQTT") @@ -165,7 +164,7 @@ struct NodeListItem: View { .frame(width: 30) } if node.hasEnvironmentMetrics { - Image(systemName: "cloud.sun.rain") + Image(systemName: "cloud.sun.rain.fill") .symbolRenderingMode(.hierarchical) .font(.callout) .frame(width: 30) @@ -190,13 +189,13 @@ struct NodeListItem: View { HStack { Image(systemName: "hare") .font(.callout) - .symbolRenderingMode(.hierarchical) + .symbolRenderingMode(.multicolor) Text("Hops Away:") - .foregroundColor(.gray) + .foregroundColor(.secondary) .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) Image(systemName: "\(node.hopsAway).square") .font(.title2) - .symbolRenderingMode(.hierarchical) + .symbolRenderingMode(.multicolor) } } else { if node.snr != 0 && !node.viaMqtt { diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index d1530274..faad71ad 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -502,7 +502,6 @@ struct Settings: View { } } } - .listStyle(.insetGrouped) .navigationTitle("settings") .navigationBarItems( leading: MeshtasticLogo()