mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge branch 'main'
This commit is contained in:
commit
65e8ae4071
2 changed files with 80 additions and 51 deletions
|
|
@ -14631,6 +14631,9 @@
|
|||
},
|
||||
"Mininum time between detection broadcasts. Default is 45 seconds." : {
|
||||
|
||||
},
|
||||
"Minute" : {
|
||||
|
||||
},
|
||||
"mode" : {
|
||||
"localizations" : {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ struct DeviceMetricsLog: View {
|
|||
@ObservedObject var node: NodeInfoEntity
|
||||
@State private var sortOrder = [KeyPathComparator(\TelemetryEntity.time, order: .reverse)]
|
||||
@State private var selection: TelemetryEntity.ID?
|
||||
@State private var chartSelection: Date?
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
|
|
@ -35,60 +36,79 @@ 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 {
|
||||
LineMark(
|
||||
x: .value("x", point.time!),
|
||||
y: .value("y", point.batteryLevel)
|
||||
)
|
||||
if #available(iOS 17.0, macOS 14.0, *) {
|
||||
Chart {
|
||||
ForEach(chartData, id: \.self) { point in
|
||||
Plot {
|
||||
LineMark(
|
||||
x: .value("x", point.time!),
|
||||
y: .value("y", point.batteryLevel)
|
||||
)
|
||||
}
|
||||
.accessibilityLabel("Line Series")
|
||||
.accessibilityValue("X: \(point.time!), Y: \(point.batteryLevel)")
|
||||
.foregroundStyle(batteryChartColor)
|
||||
.interpolationMethod(.linear)
|
||||
Plot {
|
||||
PointMark(
|
||||
x: .value("x", point.time!),
|
||||
y: .value("y", point.channelUtilization)
|
||||
)
|
||||
.symbolSize(25)
|
||||
}
|
||||
.accessibilityLabel("Line Series")
|
||||
.accessibilityValue("X: \(point.time!), Y: \(point.channelUtilization)")
|
||||
.foregroundStyle(channelUtilizationChartColor)
|
||||
if let chartSelection {
|
||||
RuleMark(x: .value("Minute", chartSelection, unit: .minute))
|
||||
.foregroundStyle(.tertiary.opacity(0.5))
|
||||
// .annotation(
|
||||
// position: .automatic,
|
||||
// overflowResolution: .init(x: .fit, y: .disabled)
|
||||
// ) {
|
||||
// ZStack {
|
||||
// Text("\(getTelemetry(for: chartSelection))")
|
||||
// }
|
||||
// .padding()
|
||||
// .background {
|
||||
// RoundedRectangle(cornerRadius: 4)
|
||||
// .foregroundStyle(Color.accentColor.opacity(0.2))
|
||||
// }
|
||||
// }
|
||||
}
|
||||
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)
|
||||
Plot {
|
||||
PointMark(
|
||||
x: .value("x", point.time!),
|
||||
y: .value("y", point.airUtilTx)
|
||||
)
|
||||
.symbolSize(25)
|
||||
}
|
||||
.accessibilityLabel("Line Series")
|
||||
.accessibilityValue("X: \(point.time!), Y: \(point.airUtilTx)")
|
||||
.foregroundStyle(airtimeChartColor)
|
||||
}
|
||||
.accessibilityLabel("Line Series")
|
||||
.accessibilityValue("X: \(point.time!), Y: \(point.batteryLevel)")
|
||||
.foregroundStyle(batteryChartColor)
|
||||
.interpolationMethod(.linear)
|
||||
|
||||
Plot {
|
||||
PointMark(
|
||||
x: .value("x", point.time!),
|
||||
y: .value("y", point.channelUtilization)
|
||||
)
|
||||
.symbolSize(25)
|
||||
}
|
||||
.accessibilityLabel("Line Series")
|
||||
.accessibilityValue("X: \(point.time!), Y: \(point.channelUtilization)")
|
||||
.foregroundStyle(channelUtilizationChartColor)
|
||||
|
||||
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)
|
||||
|
||||
Plot {
|
||||
PointMark(
|
||||
x: .value("x", point.time!),
|
||||
y: .value("y", point.airUtilTx)
|
||||
)
|
||||
.symbolSize(25)
|
||||
}
|
||||
.accessibilityLabel("Line Series")
|
||||
.accessibilityValue("X: \(point.time!), Y: \(point.airUtilTx)")
|
||||
.foregroundStyle(airtimeChartColor)
|
||||
}
|
||||
.chartXAxis(content: {
|
||||
AxisMarks(position: .top)
|
||||
})
|
||||
.chartXAxis(.automatic)
|
||||
.chartXSelection(value: $chartSelection)
|
||||
.chartYScale(domain: 0...100)
|
||||
.chartForegroundStyleScale([
|
||||
idiom == .phone ? "Battery" : "Battery Level": batteryChartColor,
|
||||
"Channel Utilization": channelUtilizationChartColor,
|
||||
"Airtime": airtimeChartColor
|
||||
])
|
||||
.chartLegend(position: .automatic, alignment: .bottom)
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
}
|
||||
.chartXAxis(content: {
|
||||
AxisMarks(position: .top)
|
||||
})
|
||||
.chartXAxis(.automatic)
|
||||
.chartYScale(domain: 0...100)
|
||||
.chartForegroundStyleScale([
|
||||
idiom == .phone ? "Battery" : "Battery Level": batteryChartColor,
|
||||
"Channel Utilization": channelUtilizationChartColor,
|
||||
"Airtime": airtimeChartColor
|
||||
])
|
||||
.chartLegend(position: .automatic, alignment: .bottom)
|
||||
}
|
||||
.frame(minHeight: 240)
|
||||
}
|
||||
|
|
@ -191,6 +211,12 @@ struct DeviceMetricsLog: View {
|
|||
.padding(.bottom)
|
||||
.padding(.trailing)
|
||||
}
|
||||
.onChange(of: selection) { newSelection in
|
||||
guard let metrics = deviceMetrics.first(where: { $0.id == newSelection }) else {
|
||||
return
|
||||
}
|
||||
chartSelection = metrics.time
|
||||
}
|
||||
} else {
|
||||
if #available (iOS 17, *) {
|
||||
ContentUnavailableView("No Device Metrics", systemImage: "slash.circle")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue