@@ -20,7 +20,6 @@ |
||
| 20 | 20 |
43554B32244449B5004E66F5 /* MeasurementPointView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43554B31244449B5004E66F5 /* MeasurementPointView.swift */; };
|
| 21 | 21 |
43554B3424444B0E004E66F5 /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43554B3324444B0E004E66F5 /* Date.swift */; };
|
| 22 | 22 |
4360A34D241CBB3800B464F9 /* RSSIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4360A34C241CBB3800B464F9 /* RSSIView.swift */; };
|
| 23 |
- 4360A34F241D5CF100B464F9 /* MeterSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4360A34E241D5CF100B464F9 /* MeterSettingsView.swift */; };
|
|
| 24 | 23 |
437D47D12415F91B00B7768E /* LiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437D47D02415F91B00B7768E /* LiveView.swift */; };
|
| 25 | 24 |
437D47D32415FB7E00B7768E /* Decimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437D47D22415FB7E00B7768E /* Decimal.swift */; };
|
| 26 | 25 |
437D47D52415FD8C00B7768E /* RecordingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437D47D42415FD8C00B7768E /* RecordingView.swift */; };
|
@@ -98,7 +97,6 @@ |
||
| 98 | 97 |
43554B31244449B5004E66F5 /* MeasurementPointView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeasurementPointView.swift; sourceTree = "<group>"; };
|
| 99 | 98 |
43554B3324444B0E004E66F5 /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
|
| 100 | 99 |
4360A34C241CBB3800B464F9 /* RSSIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSSIView.swift; sourceTree = "<group>"; };
|
| 101 |
- 4360A34E241D5CF100B464F9 /* MeterSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeterSettingsView.swift; sourceTree = "<group>"; };
|
|
| 102 | 100 |
437D47D02415F91B00B7768E /* LiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveView.swift; sourceTree = "<group>"; };
|
| 103 | 101 |
437D47D22415FB7E00B7768E /* Decimal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Decimal.swift; sourceTree = "<group>"; };
|
| 104 | 102 |
437D47D42415FD8C00B7768E /* RecordingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordingView.swift; sourceTree = "<group>"; };
|
@@ -279,7 +277,6 @@ |
||
| 279 | 277 |
isa = PBXGroup; |
| 280 | 278 |
children = ( |
| 281 | 279 |
4383B469240FE4A600DAAEBF /* MeterView.swift */, |
| 282 |
- 4360A34E241D5CF100B464F9 /* MeterSettingsView.swift */, |
|
| 283 | 280 |
437D47D02415F91B00B7768E /* LiveView.swift */, |
| 284 | 281 |
437D47D42415FD8C00B7768E /* RecordingView.swift */, |
| 285 | 282 |
437D47D62415FDF300B7768E /* ControlView.swift */, |
@@ -1,257 +0,0 @@ |
||
| 1 |
-// |
|
| 2 |
-// SettingsView.swift |
|
| 3 |
-// USB Meter |
|
| 4 |
-// |
|
| 5 |
-// Created by Bogdan Timofte on 14/03/2020. |
|
| 6 |
-// Copyright © 2020 Bogdan Timofte. All rights reserved. |
|
| 7 |
-// |
|
| 8 |
- |
|
| 9 |
-import SwiftUI |
|
| 10 |
- |
|
| 11 |
-struct MeterSettingsView: View {
|
|
| 12 |
- |
|
| 13 |
- @EnvironmentObject private var meter: Meter |
|
| 14 |
- @Environment(\.dismiss) private var dismiss |
|
| 15 |
- |
|
| 16 |
- private static let isMacIPadApp: Bool = ProcessInfo.processInfo.isiOSAppOnMac |
|
| 17 |
- |
|
| 18 |
- @State private var editingName = false |
|
| 19 |
- @State private var editingScreenTimeout = false |
|
| 20 |
- @State private var editingScreenBrightness = false |
|
| 21 |
- |
|
| 22 |
- var body: some View {
|
|
| 23 |
- VStack(spacing: 0) {
|
|
| 24 |
- if Self.isMacIPadApp {
|
|
| 25 |
- macSettingsHeader |
|
| 26 |
- } |
|
| 27 |
- ScrollView {
|
|
| 28 |
- VStack (spacing: 14) {
|
|
| 29 |
- settingsCard(title: "Name", tint: meter.color) {
|
|
| 30 |
- HStack {
|
|
| 31 |
- Spacer() |
|
| 32 |
- if !editingName {
|
|
| 33 |
- Text(meter.name) |
|
| 34 |
- .foregroundColor(.secondary) |
|
| 35 |
- } |
|
| 36 |
- ChevronView(rotate: $editingName) |
|
| 37 |
- } |
|
| 38 |
- if editingName {
|
|
| 39 |
- EditNameView(editingName: $editingName, newName: meter.name) |
|
| 40 |
- } |
|
| 41 |
- } |
|
| 42 |
- |
|
| 43 |
- if meter.operationalState == .dataIsAvailable && meter.supportsManualTemperatureUnitSelection {
|
|
| 44 |
- settingsCard(title: "Meter Temperature Unit", tint: .orange) {
|
|
| 45 |
- Text("TC66 temperature is shown as degrees without assuming Celsius or Fahrenheit. Keep this matched to the unit configured on the device so you can interpret the reading correctly.")
|
|
| 46 |
- .font(.footnote) |
|
| 47 |
- .foregroundColor(.secondary) |
|
| 48 |
- Picker("", selection: $meter.tc66TemperatureUnitPreference) {
|
|
| 49 |
- ForEach(TemperatureUnitPreference.allCases) { unit in
|
|
| 50 |
- Text(unit.title).tag(unit) |
|
| 51 |
- } |
|
| 52 |
- } |
|
| 53 |
- .pickerStyle(SegmentedPickerStyle()) |
|
| 54 |
- } |
|
| 55 |
- } |
|
| 56 |
- |
|
| 57 |
- if meter.operationalState == .dataIsAvailable {
|
|
| 58 |
- settingsCard( |
|
| 59 |
- title: meter.reportsCurrentScreenIndex ? "Screen Controls" : "Page Controls", |
|
| 60 |
- tint: .indigo |
|
| 61 |
- ) {
|
|
| 62 |
- if meter.reportsCurrentScreenIndex {
|
|
| 63 |
- Text("Use these controls when you want to change the screen shown on the device without crowding the main meter view.")
|
|
| 64 |
- .font(.footnote) |
|
| 65 |
- .foregroundColor(.secondary) |
|
| 66 |
- } else {
|
|
| 67 |
- Text("Use these controls when you want to switch device pages without crowding the main meter view.")
|
|
| 68 |
- .font(.footnote) |
|
| 69 |
- .foregroundColor(.secondary) |
|
| 70 |
- } |
|
| 71 |
- |
|
| 72 |
- ControlView(showsHeader: false) |
|
| 73 |
- } |
|
| 74 |
- } |
|
| 75 |
- |
|
| 76 |
- if meter.operationalState == .dataIsAvailable && meter.supportsUMSettings {
|
|
| 77 |
- settingsCard(title: "Screen Timeout", tint: .purple) {
|
|
| 78 |
- HStack {
|
|
| 79 |
- Spacer() |
|
| 80 |
- if !editingScreenTimeout {
|
|
| 81 |
- Text(meter.screenTimeout != 0 ? "\(meter.screenTimeout) Minutes" : "Off") |
|
| 82 |
- .foregroundColor(.secondary) |
|
| 83 |
- } |
|
| 84 |
- ChevronView(rotate: $editingScreenTimeout) |
|
| 85 |
- } |
|
| 86 |
- if editingScreenTimeout {
|
|
| 87 |
- EditScreenTimeoutView() |
|
| 88 |
- } |
|
| 89 |
- } |
|
| 90 |
- |
|
| 91 |
- settingsCard(title: "Screen Brightness", tint: .yellow) {
|
|
| 92 |
- HStack {
|
|
| 93 |
- Spacer() |
|
| 94 |
- if !editingScreenBrightness {
|
|
| 95 |
- Text("\(meter.screenBrightness)")
|
|
| 96 |
- .foregroundColor(.secondary) |
|
| 97 |
- } |
|
| 98 |
- ChevronView(rotate: $editingScreenBrightness) |
|
| 99 |
- } |
|
| 100 |
- if editingScreenBrightness {
|
|
| 101 |
- EditScreenBrightnessView() |
|
| 102 |
- } |
|
| 103 |
- } |
|
| 104 |
- } |
|
| 105 |
- } |
|
| 106 |
- .padding() |
|
| 107 |
- } |
|
| 108 |
- .background( |
|
| 109 |
- LinearGradient( |
|
| 110 |
- colors: [meter.color.opacity(0.14), Color.clear], |
|
| 111 |
- startPoint: .topLeading, |
|
| 112 |
- endPoint: .bottomTrailing |
|
| 113 |
- ) |
|
| 114 |
- .ignoresSafeArea() |
|
| 115 |
- ) |
|
| 116 |
- } |
|
| 117 |
- .modifier(IOSOnlySettingsNavBar( |
|
| 118 |
- apply: !Self.isMacIPadApp, |
|
| 119 |
- rssi: meter.btSerial.averageRSSI |
|
| 120 |
- )) |
|
| 121 |
- } |
|
| 122 |
- |
|
| 123 |
- // MARK: - Custom navigation header for Designed-for-iPad on Mac |
|
| 124 |
- |
|
| 125 |
- private var macSettingsHeader: some View {
|
|
| 126 |
- HStack(spacing: 12) {
|
|
| 127 |
- Button {
|
|
| 128 |
- dismiss() |
|
| 129 |
- } label: {
|
|
| 130 |
- HStack(spacing: 4) {
|
|
| 131 |
- Image(systemName: "chevron.left") |
|
| 132 |
- .font(.body.weight(.semibold)) |
|
| 133 |
- Text("Back")
|
|
| 134 |
- } |
|
| 135 |
- .foregroundColor(.accentColor) |
|
| 136 |
- } |
|
| 137 |
- .buttonStyle(.plain) |
|
| 138 |
- |
|
| 139 |
- Text("Meter Settings")
|
|
| 140 |
- .font(.headline) |
|
| 141 |
- .lineLimit(1) |
|
| 142 |
- |
|
| 143 |
- Spacer() |
|
| 144 |
- |
|
| 145 |
- if meter.operationalState > .notPresent {
|
|
| 146 |
- RSSIView(RSSI: meter.btSerial.averageRSSI) |
|
| 147 |
- .frame(width: 18, height: 18) |
|
| 148 |
- } |
|
| 149 |
- } |
|
| 150 |
- .padding(.horizontal, 16) |
|
| 151 |
- .padding(.vertical, 10) |
|
| 152 |
- .background( |
|
| 153 |
- Rectangle() |
|
| 154 |
- .fill(.ultraThinMaterial) |
|
| 155 |
- .ignoresSafeArea(edges: .top) |
|
| 156 |
- ) |
|
| 157 |
- .overlay(alignment: .bottom) {
|
|
| 158 |
- Rectangle() |
|
| 159 |
- .fill(Color.secondary.opacity(0.12)) |
|
| 160 |
- .frame(height: 1) |
|
| 161 |
- } |
|
| 162 |
- } |
|
| 163 |
- |
|
| 164 |
- private func settingsCard<Content: View>( |
|
| 165 |
- title: String, |
|
| 166 |
- tint: Color, |
|
| 167 |
- @ViewBuilder content: () -> Content |
|
| 168 |
- ) -> some View {
|
|
| 169 |
- VStack(alignment: .leading, spacing: 12) {
|
|
| 170 |
- Text(title) |
|
| 171 |
- .font(.headline) |
|
| 172 |
- content() |
|
| 173 |
- } |
|
| 174 |
- .padding(18) |
|
| 175 |
- .meterCard(tint: tint, fillOpacity: 0.18, strokeOpacity: 0.24) |
|
| 176 |
- } |
|
| 177 |
-} |
|
| 178 |
- |
|
| 179 |
-struct EditNameView: View {
|
|
| 180 |
- |
|
| 181 |
- @EnvironmentObject private var meter: Meter |
|
| 182 |
- |
|
| 183 |
- @Binding var editingName: Bool |
|
| 184 |
- @State var newName: String |
|
| 185 |
- |
|
| 186 |
- var body: some View {
|
|
| 187 |
- TextField("Name", text: self.$newName, onCommit: {
|
|
| 188 |
- self.meter.name = self.newName |
|
| 189 |
- self.editingName = false |
|
| 190 |
- }) |
|
| 191 |
- .textFieldStyle(RoundedBorderTextFieldStyle()) |
|
| 192 |
- .lineLimit(1) |
|
| 193 |
- .disableAutocorrection(true) |
|
| 194 |
- .multilineTextAlignment(.center) |
|
| 195 |
- } |
|
| 196 |
-} |
|
| 197 |
- |
|
| 198 |
-struct EditScreenTimeoutView: View {
|
|
| 199 |
- |
|
| 200 |
- @EnvironmentObject private var meter: Meter |
|
| 201 |
- |
|
| 202 |
- var body: some View {
|
|
| 203 |
- Picker("", selection: self.$meter.screenTimeout ) {
|
|
| 204 |
- Text("1").tag(1)
|
|
| 205 |
- Text("2").tag(2)
|
|
| 206 |
- Text("3").tag(3)
|
|
| 207 |
- Text("4").tag(4)
|
|
| 208 |
- Text("5").tag(5)
|
|
| 209 |
- Text("6").tag(6)
|
|
| 210 |
- Text("7").tag(7)
|
|
| 211 |
- Text("8").tag(8)
|
|
| 212 |
- Text("9").tag(9)
|
|
| 213 |
- Text("Off").tag(0)
|
|
| 214 |
- } |
|
| 215 |
- .pickerStyle( SegmentedPickerStyle() ) |
|
| 216 |
- } |
|
| 217 |
-} |
|
| 218 |
- |
|
| 219 |
-struct EditScreenBrightnessView: View {
|
|
| 220 |
- |
|
| 221 |
- @EnvironmentObject private var meter: Meter |
|
| 222 |
- |
|
| 223 |
- var body: some View {
|
|
| 224 |
- Picker("", selection: self.$meter.screenBrightness ) {
|
|
| 225 |
- Text("0").tag(0)
|
|
| 226 |
- Text("1").tag(1)
|
|
| 227 |
- Text("2").tag(2)
|
|
| 228 |
- Text("3").tag(3)
|
|
| 229 |
- Text("4").tag(4)
|
|
| 230 |
- Text("5").tag(5)
|
|
| 231 |
- } |
|
| 232 |
- .pickerStyle( SegmentedPickerStyle() ) |
|
| 233 |
- } |
|
| 234 |
-} |
|
| 235 |
- |
|
| 236 |
-// MARK: - Conditional navigation bar modifier (skipped on Designed-for-iPad / Mac) |
|
| 237 |
- |
|
| 238 |
-private struct IOSOnlySettingsNavBar: ViewModifier {
|
|
| 239 |
- let apply: Bool |
|
| 240 |
- let rssi: Int |
|
| 241 |
- |
|
| 242 |
- @ViewBuilder |
|
| 243 |
- func body(content: Content) -> some View {
|
|
| 244 |
- if apply {
|
|
| 245 |
- content |
|
| 246 |
- .navigationBarTitle("Meter Settings")
|
|
| 247 |
- .toolbar {
|
|
| 248 |
- ToolbarItem(placement: .navigationBarTrailing) {
|
|
| 249 |
- RSSIView(RSSI: rssi).frame(width: 18, height: 18) |
|
| 250 |
- } |
|
| 251 |
- } |
|
| 252 |
- } else {
|
|
| 253 |
- content |
|
| 254 |
- .navigationBarHidden(true) |
|
| 255 |
- } |
|
| 256 |
- } |
|
| 257 |
-} |
|
@@ -15,12 +15,14 @@ struct MeterView: View {
|
||
| 15 | 15 |
case connection |
| 16 | 16 |
case live |
| 17 | 17 |
case chart |
| 18 |
+ case settings |
|
| 18 | 19 |
|
| 19 | 20 |
var title: String {
|
| 20 | 21 |
switch self {
|
| 21 | 22 |
case .connection: return "Home" |
| 22 | 23 |
case .live: return "Live" |
| 23 | 24 |
case .chart: return "Chart" |
| 25 |
+ case .settings: return "Settings" |
|
| 24 | 26 |
} |
| 25 | 27 |
} |
| 26 | 28 |
|
@@ -29,6 +31,7 @@ struct MeterView: View {
|
||
| 29 | 31 |
case .connection: return "house.fill" |
| 30 | 32 |
case .live: return "waveform.path.ecg" |
| 31 | 33 |
case .chart: return "chart.xyaxis.line" |
| 34 |
+ case .settings: return "gearshape.fill" |
|
| 32 | 35 |
} |
| 33 | 36 |
} |
| 34 | 37 |
} |
@@ -45,6 +48,9 @@ struct MeterView: View {
|
||
| 45 | 48 |
@State private var navBarTitle: String = "Meter" |
| 46 | 49 |
@State private var navBarShowRSSI: Bool = false |
| 47 | 50 |
@State private var navBarRSSI: Int = 0 |
| 51 |
+ @State private var editingName = false |
|
| 52 |
+ @State private var editingScreenTimeout = false |
|
| 53 |
+ @State private var editingScreenBrightness = false |
|
| 48 | 54 |
private var myBounds: CGRect { UIScreen.main.bounds }
|
| 49 | 55 |
private let actionStripPadding: CGFloat = 10 |
| 50 | 56 |
private let actionDividerWidth: CGFloat = 1 |
@@ -129,11 +135,6 @@ struct MeterView: View {
|
||
| 129 | 135 |
.frame(width: 18, height: 18) |
| 130 | 136 |
} |
| 131 | 137 |
|
| 132 |
- NavigationLink(destination: MeterSettingsView().environmentObject(meter)) {
|
|
| 133 |
- Image(systemName: "gearshape.fill") |
|
| 134 |
- .foregroundColor(.accentColor) |
|
| 135 |
- } |
|
| 136 |
- .buttonStyle(.plain) |
|
| 137 | 138 |
} |
| 138 | 139 |
.padding(.horizontal, 16) |
| 139 | 140 |
.padding(.vertical, 10) |
@@ -270,6 +271,8 @@ struct MeterView: View {
|
||
| 270 | 271 |
} else {
|
| 271 | 272 |
landscapeConnectionPage |
| 272 | 273 |
} |
| 274 |
+ case .settings: |
|
| 275 |
+ landscapeSettingsPage(size: size) |
|
| 273 | 276 |
} |
| 274 | 277 |
} |
| 275 | 278 |
|
@@ -290,6 +293,8 @@ struct MeterView: View {
|
||
| 290 | 293 |
} else {
|
| 291 | 294 |
portraitConnectionPage(size: size) |
| 292 | 295 |
} |
| 296 |
+ case .settings: |
|
| 297 |
+ portraitSettingsPage(size: size) |
|
| 293 | 298 |
} |
| 294 | 299 |
} |
| 295 | 300 |
|
@@ -410,6 +415,166 @@ struct MeterView: View {
|
||
| 410 | 415 |
} |
| 411 | 416 |
} |
| 412 | 417 |
|
| 418 |
+ @ViewBuilder |
|
| 419 |
+ private func portraitSettingsPage(size: CGSize) -> some View {
|
|
| 420 |
+ settingsTabContent |
|
| 421 |
+ } |
|
| 422 |
+ |
|
| 423 |
+ @ViewBuilder |
|
| 424 |
+ private func landscapeSettingsPage(size: CGSize) -> some View {
|
|
| 425 |
+ settingsTabContent |
|
| 426 |
+ } |
|
| 427 |
+ |
|
| 428 |
+ private var settingsTabContent: some View {
|
|
| 429 |
+ VStack(spacing: 0) {
|
|
| 430 |
+ if Self.isMacIPadApp {
|
|
| 431 |
+ settingsMacHeader |
|
| 432 |
+ } |
|
| 433 |
+ ScrollView {
|
|
| 434 |
+ VStack(spacing: 14) {
|
|
| 435 |
+ settingsCard(title: "Name", tint: meter.color) {
|
|
| 436 |
+ HStack {
|
|
| 437 |
+ Spacer() |
|
| 438 |
+ if !editingName {
|
|
| 439 |
+ Text(meter.name) |
|
| 440 |
+ .foregroundColor(.secondary) |
|
| 441 |
+ } |
|
| 442 |
+ ChevronView(rotate: $editingName) |
|
| 443 |
+ } |
|
| 444 |
+ if editingName {
|
|
| 445 |
+ EditNameView(editingName: $editingName, newName: meter.name) |
|
| 446 |
+ } |
|
| 447 |
+ } |
|
| 448 |
+ |
|
| 449 |
+ if meter.operationalState == .dataIsAvailable && meter.supportsManualTemperatureUnitSelection {
|
|
| 450 |
+ settingsCard(title: "Meter Temperature Unit", tint: .orange) {
|
|
| 451 |
+ Text("TC66 temperature is shown as degrees without assuming Celsius or Fahrenheit. Keep this matched to the unit configured on the device so you can interpret the reading correctly.")
|
|
| 452 |
+ .font(.footnote) |
|
| 453 |
+ .foregroundColor(.secondary) |
|
| 454 |
+ Picker("", selection: $meter.tc66TemperatureUnitPreference) {
|
|
| 455 |
+ ForEach(TemperatureUnitPreference.allCases) { unit in
|
|
| 456 |
+ Text(unit.title).tag(unit) |
|
| 457 |
+ } |
|
| 458 |
+ } |
|
| 459 |
+ .pickerStyle(SegmentedPickerStyle()) |
|
| 460 |
+ } |
|
| 461 |
+ } |
|
| 462 |
+ |
|
| 463 |
+ if meter.operationalState == .dataIsAvailable {
|
|
| 464 |
+ settingsCard( |
|
| 465 |
+ title: meter.reportsCurrentScreenIndex ? "Screen Controls" : "Page Controls", |
|
| 466 |
+ tint: .indigo |
|
| 467 |
+ ) {
|
|
| 468 |
+ if meter.reportsCurrentScreenIndex {
|
|
| 469 |
+ Text("Use these controls when you want to change the screen shown on the device without crowding the main meter view.")
|
|
| 470 |
+ .font(.footnote) |
|
| 471 |
+ .foregroundColor(.secondary) |
|
| 472 |
+ } else {
|
|
| 473 |
+ Text("Use these controls when you want to switch device pages without crowding the main meter view.")
|
|
| 474 |
+ .font(.footnote) |
|
| 475 |
+ .foregroundColor(.secondary) |
|
| 476 |
+ } |
|
| 477 |
+ |
|
| 478 |
+ ControlView(showsHeader: false) |
|
| 479 |
+ } |
|
| 480 |
+ } |
|
| 481 |
+ |
|
| 482 |
+ if meter.operationalState == .dataIsAvailable && meter.supportsUMSettings {
|
|
| 483 |
+ settingsCard(title: "Screen Timeout", tint: .purple) {
|
|
| 484 |
+ HStack {
|
|
| 485 |
+ Spacer() |
|
| 486 |
+ if !editingScreenTimeout {
|
|
| 487 |
+ Text(meter.screenTimeout > 0 ? "\(meter.screenTimeout) Minutes" : "Off") |
|
| 488 |
+ .foregroundColor(.secondary) |
|
| 489 |
+ } |
|
| 490 |
+ ChevronView(rotate: $editingScreenTimeout) |
|
| 491 |
+ } |
|
| 492 |
+ if editingScreenTimeout {
|
|
| 493 |
+ EditScreenTimeoutView() |
|
| 494 |
+ } |
|
| 495 |
+ } |
|
| 496 |
+ |
|
| 497 |
+ settingsCard(title: "Screen Brightness", tint: .yellow) {
|
|
| 498 |
+ HStack {
|
|
| 499 |
+ Spacer() |
|
| 500 |
+ if !editingScreenBrightness {
|
|
| 501 |
+ Text("\(meter.screenBrightness)")
|
|
| 502 |
+ .foregroundColor(.secondary) |
|
| 503 |
+ } |
|
| 504 |
+ ChevronView(rotate: $editingScreenBrightness) |
|
| 505 |
+ } |
|
| 506 |
+ if editingScreenBrightness {
|
|
| 507 |
+ EditScreenBrightnessView() |
|
| 508 |
+ } |
|
| 509 |
+ } |
|
| 510 |
+ } |
|
| 511 |
+ } |
|
| 512 |
+ .padding() |
|
| 513 |
+ } |
|
| 514 |
+ .background( |
|
| 515 |
+ LinearGradient( |
|
| 516 |
+ colors: [meter.color.opacity(0.14), Color.clear], |
|
| 517 |
+ startPoint: .topLeading, |
|
| 518 |
+ endPoint: .bottomTrailing |
|
| 519 |
+ ) |
|
| 520 |
+ .ignoresSafeArea() |
|
| 521 |
+ ) |
|
| 522 |
+ } |
|
| 523 |
+ } |
|
| 524 |
+ |
|
| 525 |
+ private var settingsMacHeader: some View {
|
|
| 526 |
+ HStack(spacing: 12) {
|
|
| 527 |
+ Button {
|
|
| 528 |
+ selectedMeterTab = .connection |
|
| 529 |
+ } label: {
|
|
| 530 |
+ HStack(spacing: 4) {
|
|
| 531 |
+ Image(systemName: "chevron.left") |
|
| 532 |
+ .font(.body.weight(.semibold)) |
|
| 533 |
+ Text("Back")
|
|
| 534 |
+ } |
|
| 535 |
+ .foregroundColor(.accentColor) |
|
| 536 |
+ } |
|
| 537 |
+ .buttonStyle(.plain) |
|
| 538 |
+ |
|
| 539 |
+ Text("Meter Settings")
|
|
| 540 |
+ .font(.headline) |
|
| 541 |
+ .lineLimit(1) |
|
| 542 |
+ |
|
| 543 |
+ Spacer() |
|
| 544 |
+ |
|
| 545 |
+ if meter.operationalState > .notPresent {
|
|
| 546 |
+ RSSIView(RSSI: meter.btSerial.averageRSSI) |
|
| 547 |
+ .frame(width: 18, height: 18) |
|
| 548 |
+ } |
|
| 549 |
+ } |
|
| 550 |
+ .padding(.horizontal, 16) |
|
| 551 |
+ .padding(.vertical, 10) |
|
| 552 |
+ .background( |
|
| 553 |
+ Rectangle() |
|
| 554 |
+ .fill(.ultraThinMaterial) |
|
| 555 |
+ .ignoresSafeArea(edges: .top) |
|
| 556 |
+ ) |
|
| 557 |
+ .overlay(alignment: .bottom) {
|
|
| 558 |
+ Rectangle() |
|
| 559 |
+ .fill(Color.secondary.opacity(0.12)) |
|
| 560 |
+ .frame(height: 1) |
|
| 561 |
+ } |
|
| 562 |
+ } |
|
| 563 |
+ |
|
| 564 |
+ private func settingsCard<Content: View>( |
|
| 565 |
+ title: String, |
|
| 566 |
+ tint: Color, |
|
| 567 |
+ @ViewBuilder content: () -> Content |
|
| 568 |
+ ) -> some View {
|
|
| 569 |
+ VStack(alignment: .leading, spacing: 12) {
|
|
| 570 |
+ Text(title) |
|
| 571 |
+ .font(.headline) |
|
| 572 |
+ content() |
|
| 573 |
+ } |
|
| 574 |
+ .padding(18) |
|
| 575 |
+ .meterCard(tint: tint, fillOpacity: 0.18, strokeOpacity: 0.24) |
|
| 576 |
+ } |
|
| 577 |
+ |
|
| 413 | 578 |
private var availableMeterTabs: [MeterTab] {
|
| 414 | 579 |
var tabs: [MeterTab] = [.connection] |
| 415 | 580 |
|
@@ -421,6 +586,8 @@ struct MeterView: View {
|
||
| 421 | 586 |
} |
| 422 | 587 |
} |
| 423 | 588 |
|
| 589 |
+ tabs.append(.settings) |
|
| 590 |
+ |
|
| 424 | 591 |
return tabs |
| 425 | 592 |
} |
| 426 | 593 |
|
@@ -727,6 +894,54 @@ private struct MeterInfoRow: View {
|
||
| 727 | 894 |
} |
| 728 | 895 |
} |
| 729 | 896 |
|
| 897 |
+private struct EditNameView: View {
|
|
| 898 |
+ |
|
| 899 |
+ @EnvironmentObject private var meter: Meter |
|
| 900 |
+ |
|
| 901 |
+ @Binding var editingName: Bool |
|
| 902 |
+ @State var newName: String |
|
| 903 |
+ |
|
| 904 |
+ var body: some View {
|
|
| 905 |
+ TextField("Name", text: self.$newName, onCommit: {
|
|
| 906 |
+ self.meter.name = self.newName |
|
| 907 |
+ self.editingName = false |
|
| 908 |
+ }) |
|
| 909 |
+ .textFieldStyle(RoundedBorderTextFieldStyle()) |
|
| 910 |
+ .lineLimit(1) |
|
| 911 |
+ .disableAutocorrection(true) |
|
| 912 |
+ .multilineTextAlignment(.center) |
|
| 913 |
+ } |
|
| 914 |
+} |
|
| 915 |
+ |
|
| 916 |
+private struct EditScreenTimeoutView: View {
|
|
| 917 |
+ |
|
| 918 |
+ @EnvironmentObject private var meter: Meter |
|
| 919 |
+ |
|
| 920 |
+ var body: some View {
|
|
| 921 |
+ Picker("", selection: self.$meter.screenTimeout ) {
|
|
| 922 |
+ ForEach(1...9, id: \.self) { value in
|
|
| 923 |
+ Text("\(value)").tag(value)
|
|
| 924 |
+ } |
|
| 925 |
+ Text("Off").tag(0)
|
|
| 926 |
+ } |
|
| 927 |
+ .pickerStyle(SegmentedPickerStyle()) |
|
| 928 |
+ } |
|
| 929 |
+} |
|
| 930 |
+ |
|
| 931 |
+private struct EditScreenBrightnessView: View {
|
|
| 932 |
+ |
|
| 933 |
+ @EnvironmentObject private var meter: Meter |
|
| 934 |
+ |
|
| 935 |
+ var body: some View {
|
|
| 936 |
+ Picker("", selection: self.$meter.screenBrightness ) {
|
|
| 937 |
+ ForEach(0...5, id: \.self) { value in
|
|
| 938 |
+ Text("\(value)").tag(value)
|
|
| 939 |
+ } |
|
| 940 |
+ } |
|
| 941 |
+ .pickerStyle(SegmentedPickerStyle()) |
|
| 942 |
+ } |
|
| 943 |
+} |
|
| 944 |
+ |
|
| 730 | 945 |
// MARK: - Conditional navigation bar modifier (skipped on Designed-for-iPad / Mac) |
| 731 | 946 |
|
| 732 | 947 |
private struct IOSOnlyNavBar: ViewModifier {
|
@@ -747,9 +962,6 @@ private struct IOSOnlyNavBar: ViewModifier {
|
||
| 747 | 962 |
RSSIView(RSSI: rssi) |
| 748 | 963 |
.frame(width: 18, height: 18) |
| 749 | 964 |
} |
| 750 |
- NavigationLink(destination: MeterSettingsView().environmentObject(meter)) {
|
|
| 751 |
- Image(systemName: "gearshape.fill") |
|
| 752 |
- } |
|
| 753 | 965 |
} |
| 754 | 966 |
} |
| 755 | 967 |
} else {
|