1 contributor
//
// MeterSettingsTabView.swift
// USB Meter
//
import SwiftUI
struct MeterSettingsTabView: View {
@EnvironmentObject private var appData: AppData
@EnvironmentObject private var meter: Meter
let isMacIPadApp: Bool
let onBackToHome: () -> Void
@State private var editingName = false
@State private var editingScreenTimeout = false
@State private var editingScreenBrightness = false
@State private var deleteConfirmationVisibility = false
var body: some View {
VStack(spacing: 0) {
if isMacIPadApp {
settingsMacHeader
}
ScrollView {
VStack(spacing: 14) {
settingsCard(title: "Name", tint: meter.color) {
HStack {
Spacer()
if !editingName {
Text(meter.name)
.foregroundColor(.secondary)
}
ChevronView(rotate: $editingName)
}
if editingName {
MeterNameEditorView(editingName: $editingName, newName: meter.name)
}
}
if meter.operationalState == .dataIsAvailable && meter.supportsManualTemperatureUnitSelection {
settingsCard(
title: "Meter Temperature Unit",
infoMessage: "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.",
tint: .orange
) {
Picker("", selection: $meter.tc66TemperatureUnitPreference) {
ForEach(TemperatureUnitPreference.allCases) { unit in
Text(unit.title).tag(unit)
}
}
.pickerStyle(SegmentedPickerStyle())
}
}
if meter.operationalState == .dataIsAvailable && meter.model == .TC66C {
settingsCard(
title: "Screen Reporting",
infoMessage: "TC66 is the exception: it does not report the current screen in the payload, so the app keeps this note here instead of showing it on the home screen.",
tint: .orange
) {
MeterInfoRowView(label: "Current Screen", value: "Not Reported")
}
}
if meter.operationalState == .dataIsAvailable {
settingsCard(
title: meter.reportsCurrentScreenIndex ? "Screen Controls" : "Page Controls",
infoMessage: meter.reportsCurrentScreenIndex
? "Use these controls when you want to change the screen shown on the device without crowding the main meter view."
: "Use these controls when you want to switch device pages without crowding the main meter view.",
tint: .indigo
) {
MeterScreenControlsView(showsHeader: false)
}
}
if meter.operationalState == .dataIsAvailable && meter.supportsUMSettings {
settingsCard(title: "Screen Timeout", tint: .purple) {
HStack {
Spacer()
if !editingScreenTimeout {
Text(meter.screenTimeout > 0 ? "\(meter.screenTimeout) Minutes" : "Off")
.foregroundColor(.secondary)
}
ChevronView(rotate: $editingScreenTimeout)
}
if editingScreenTimeout {
ScreenTimeoutEditorView()
}
}
settingsCard(title: "Screen Brightness", tint: .yellow) {
HStack {
Spacer()
if !editingScreenBrightness {
Text("\(meter.screenBrightness)")
.foregroundColor(.secondary)
}
ChevronView(rotate: $editingScreenBrightness)
}
if editingScreenBrightness {
ScreenBrightnessEditorView()
}
}
}
settingsCard(
title: "Danger Zone",
infoMessage: "Delete this meter from the sidebar and clear its saved metadata. If the device is still nearby, it can appear again after a fresh Bluetooth discovery.",
tint: .red
) {
Button("Delete Meter") {
deleteConfirmationVisibility = true
}
.frame(maxWidth: .infinity)
.padding(.vertical, 10)
.meterCard(tint: .red, fillOpacity: 0.16, strokeOpacity: 0.22, cornerRadius: 14)
.buttonStyle(.plain)
}
}
.padding()
}
.background(
LinearGradient(
colors: [meter.color.opacity(0.14), Color.clear],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.ignoresSafeArea()
)
.alert("Delete Meter?", isPresented: $deleteConfirmationVisibility) {
Button("Delete", role: .destructive) {
if appData.deleteMeter(macAddress: meter.btSerial.macAddress.description) {
onBackToHome()
}
}
Button("Cancel", role: .cancel) {}
} message: {
Text("This removes the saved meter entry and disconnects the live meter view.")
}
}
}
private var settingsMacHeader: some View {
HStack(spacing: 12) {
Button(action: onBackToHome) {
HStack(spacing: 4) {
Image(systemName: "chevron.left")
.font(.body.weight(.semibold))
Text("Back")
}
.foregroundColor(.accentColor)
}
.buttonStyle(.plain)
Text("Meter Settings")
.font(.headline)
.lineLimit(1)
Spacer()
if meter.operationalState > .notPresent {
RSSIView(RSSI: meter.btSerial.averageRSSI)
.frame(width: 18, height: 18)
}
}
.padding(.horizontal, 16)
.padding(.vertical, 10)
.background(
Rectangle()
.fill(.ultraThinMaterial)
.ignoresSafeArea(edges: .top)
)
.overlay(alignment: .bottom) {
Rectangle()
.fill(Color.secondary.opacity(0.12))
.frame(height: 1)
}
}
private func settingsCard<Content: View>(
title: String,
infoMessage: String? = nil,
tint: Color,
@ViewBuilder content: () -> Content
) -> some View {
VStack(alignment: .leading, spacing: 12) {
HStack(spacing: 8) {
Text(title)
.font(.headline)
if let infoMessage {
ContextInfoButton(title: title, message: infoMessage)
}
}
content()
}
.padding(18)
.meterCard(tint: tint, fillOpacity: 0.18, strokeOpacity: 0.24)
}
}