mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Improvements for iPad and Mac Catalyst
This commit is contained in:
parent
76dfc9647e
commit
4e57daaf8f
5 changed files with 85 additions and 58 deletions
|
|
@ -132,9 +132,6 @@
|
|||
},
|
||||
"%@ dB" : {
|
||||
|
||||
},
|
||||
"%@ hPa" : {
|
||||
|
||||
},
|
||||
"%@, %@" : {
|
||||
"localizations" : {
|
||||
|
|
@ -6956,6 +6953,9 @@
|
|||
},
|
||||
"Documentation" : {
|
||||
|
||||
},
|
||||
"Done" : {
|
||||
|
||||
},
|
||||
"Double Tap as Button" : {
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,11 @@ class MetricsColumnList: ObservableObject, RandomAccessCollection, RangeReplacea
|
|||
}
|
||||
return returnValues
|
||||
}
|
||||
|
||||
|
||||
func column(forAttribute attribute: String) -> MetricsTableColumn? {
|
||||
return columns.first(where: { $0.attribute == attribute})
|
||||
}
|
||||
|
||||
// Collection conformance
|
||||
typealias Index = Int
|
||||
typealias Element = MetricsTableColumn
|
||||
|
|
|
|||
|
|
@ -49,36 +49,32 @@ struct EnvironmentMetricsLog: View {
|
|||
.chartLegend(position: .automatic, alignment: .bottom)
|
||||
}
|
||||
}
|
||||
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current)
|
||||
let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "")
|
||||
|
||||
// Dynamic table column using SwiftUI Table requires TableColumnForEach which requires the target
|
||||
// to be bumped to 17.4 -- Until that happens, the existing non-configurable table is used.
|
||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
// Add a table for mac and ipad
|
||||
Table(environmentMetrics) {
|
||||
TableColumn("Temperature") { em in
|
||||
Text(em.temperature.formattedTemperature())
|
||||
columnList.column(forAttribute: "temperature")?.body(em)
|
||||
}
|
||||
TableColumn("Humidity") { em in
|
||||
Text("\(String(format: "%.0f", em.relativeHumidity))%")
|
||||
columnList.column(forAttribute: "relativeHumidity")?.body(em)
|
||||
}
|
||||
TableColumn("Barometric Pressure") { em in
|
||||
Text("\(String(format: "%.1f", em.barometricPressure)) hPa")
|
||||
columnList.column(forAttribute: "barometricPressure")?.body(em)
|
||||
}
|
||||
TableColumn("Indoor Air Quality") { em in
|
||||
HStack {
|
||||
Text("IAQ")
|
||||
IndoorAirQuality(iaq: Int(em.iaq), displayMode: IaqDisplayMode.dot )
|
||||
}
|
||||
columnList.column(forAttribute: "iaq")?.body(em)
|
||||
}
|
||||
TableColumn("Wind Speed") { em in
|
||||
let windSpeed = Measurement(value: Double(em.windSpeed), unit: UnitSpeed.kilometersPerHour)
|
||||
Text(windSpeed.formatted(.measurement(width: .abbreviated, numberFormatStyle: .number.precision(.fractionLength(0)))))
|
||||
columnList.column(forAttribute: "windSpeed")?.body(em)
|
||||
}
|
||||
TableColumn("Wind Direction") { em in
|
||||
let direction = cardinalValue(from: Double(em.windDirection))
|
||||
Text(direction)
|
||||
columnList.column(forAttribute: "windDirection")?.body(em)
|
||||
}
|
||||
TableColumn("timestamp") { em in
|
||||
Text(em.time?.formattedDate(format: dateFormatString) ?? "unknown.age".localized)
|
||||
columnList.column(forAttribute: "time")?.body(em)
|
||||
}
|
||||
.width(min: 180)
|
||||
}
|
||||
|
|
@ -96,6 +92,7 @@ struct EnvironmentMetricsLog: View {
|
|||
GridRow {
|
||||
ForEach(columnList.visible) { col in
|
||||
col.body(em)
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ extension MetricsColumnList {
|
|||
minWidth: 25, maxWidth: 40,
|
||||
tableBody: { _, temp in
|
||||
Text(temp.formattedTemperature())
|
||||
.font(.caption)
|
||||
}),
|
||||
|
||||
// Relative Humidity Series Configuration
|
||||
|
|
@ -32,7 +31,6 @@ extension MetricsColumnList {
|
|||
minWidth: 25, maxWidth: 40,
|
||||
tableBody: { _, humidity in
|
||||
Text("\(String(format: "%.0f", humidity))%")
|
||||
.font(.caption)
|
||||
}),
|
||||
|
||||
// Barometric Pressure Series Configuration
|
||||
|
|
@ -42,8 +40,11 @@ extension MetricsColumnList {
|
|||
abbreviatedName: "Bar",
|
||||
minWidth: 30, maxWidth: 50,
|
||||
tableBody: { _, pressure in
|
||||
Text("\(String(format: "%.1f", pressure))")
|
||||
.font(.caption)
|
||||
if (UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac) {
|
||||
Text("\(String(format: "%.1f hPa", pressure))")
|
||||
} else {
|
||||
Text("\(String(format: "%.1f", pressure))")
|
||||
}
|
||||
}),
|
||||
|
||||
// Indoor Air Quality Series Configuration
|
||||
|
|
@ -54,7 +55,6 @@ extension MetricsColumnList {
|
|||
minWidth: 25, maxWidth: 50,
|
||||
tableBody: { _, iaq in
|
||||
IndoorAirQuality(iaq: Int(iaq), displayMode: .dot)
|
||||
.font(.caption)
|
||||
}),
|
||||
|
||||
// Wind Direction Series Configuration
|
||||
|
|
@ -70,9 +70,14 @@ extension MetricsColumnList {
|
|||
let wind = Double(wind)
|
||||
Image(systemName: "location.north")
|
||||
.imageScale(.small)
|
||||
.scaleEffect(0.9, anchor: .center)
|
||||
.rotationEffect(.degrees(wind))
|
||||
Text(abbreviatedCardinalValue(from: wind))
|
||||
.font(.caption)
|
||||
.foregroundStyle(.blue)
|
||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
Text(cardinalValue(from: wind))
|
||||
} else {
|
||||
Text(abbreviatedCardinalValue(from: wind))
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
|
|
@ -93,7 +98,6 @@ extension MetricsColumnList {
|
|||
numberFormatStyle: .number.precision(
|
||||
.fractionLength(0))))
|
||||
)
|
||||
.font(.caption)
|
||||
}),
|
||||
|
||||
// Timestamp Series Configuration -- for use in table only
|
||||
|
|
@ -113,7 +117,6 @@ extension MetricsColumnList {
|
|||
time?.formattedDate(format: dateFormatString)
|
||||
?? "unknown.age".localized
|
||||
)
|
||||
.font(.caption)
|
||||
})
|
||||
])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,46 +13,69 @@ struct MetricsColumnDetail: View {
|
|||
|
||||
@State private var currentDetent = PresentationDetent.medium
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section("Chart") {
|
||||
ForEach(seriesList) { series in
|
||||
HStack {
|
||||
Circle()
|
||||
.fill(series.foregroundStyle(0.0...100.0) ?? AnyShapeStyle(.clear))
|
||||
.frame(width: 20.0, height: 20.0)
|
||||
Text(series.name)
|
||||
Spacer()
|
||||
if series.visible {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}.contentShape(Rectangle()) // Ensures the entire row is tappable
|
||||
.onTapGesture {
|
||||
seriesList.toggleVisibity(for: series)
|
||||
ZStack {
|
||||
List {
|
||||
Section("Chart") {
|
||||
ForEach(seriesList) { series in
|
||||
HStack {
|
||||
Circle()
|
||||
.fill(series.foregroundStyle(0.0...100.0) ?? AnyShapeStyle(.clear))
|
||||
.frame(width: 20.0, height: 20.0)
|
||||
Text(series.name)
|
||||
Spacer()
|
||||
if series.visible {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}.contentShape(Rectangle()) // Ensures the entire row is tappable
|
||||
.onTapGesture {
|
||||
seriesList.toggleVisibity(for: series)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Dynamic table column using SwiftUI Table requires TableColumnForEach which requires the target
|
||||
// to be bumped to 17.4 -- Until that happens, the existing non-configurable table is used.
|
||||
if !(UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac) {
|
||||
Section("Table") {
|
||||
ForEach(columnList.columns) { column in
|
||||
HStack {
|
||||
Text(column.name)
|
||||
Spacer()
|
||||
if column.visible {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}.contentShape(Rectangle()) // Ensures the entire row is tappable
|
||||
.onTapGesture {
|
||||
columnList.objectWillChange.send()
|
||||
columnList.toggleVisibity(for: column)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Section("Table") {
|
||||
ForEach(columnList.columns) { column in
|
||||
HStack {
|
||||
Text(column.name)
|
||||
Spacer()
|
||||
if column.visible {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}.contentShape(Rectangle()) // Ensures the entire row is tappable
|
||||
.onTapGesture {
|
||||
columnList.objectWillChange.send()
|
||||
columnList.toggleVisibity(for: column)
|
||||
}
|
||||
|
||||
// More friendly to tap a button to dismiss on these devices
|
||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
Spacer()
|
||||
Button {
|
||||
self.dismiss()
|
||||
} label: {
|
||||
Text("Done")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding([.leading, .trailing, .bottom])
|
||||
}
|
||||
}
|
||||
.presentationDetents([.medium, .large], selection: $currentDetent)
|
||||
.presentationContentInteraction(.scrolls)
|
||||
.presentationDragIndicator(.visible)
|
||||
.presentationDragIndicator(
|
||||
!(UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac) ? .visible : .hidden)
|
||||
.presentationBackgroundInteraction(.enabled(upThrough: .medium))
|
||||
.interactiveDismissDisabled(false)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue