Newer Older
201 lines | 8.279kb
Bogdan Timofte authored 2 months ago
1
//
2
//  MeterSettingsTabView.swift
3
//  USB Meter
4
//
5

            
6
import SwiftUI
7

            
8
struct MeterSettingsTabView: View {
Bogdan Timofte authored a month ago
9
    @EnvironmentObject private var appData: AppData
Bogdan Timofte authored 2 months ago
10
    @EnvironmentObject private var meter: Meter
11

            
12
    let isMacIPadApp: Bool
13
    let onBackToHome: () -> Void
14

            
15
    @State private var editingName = false
16
    @State private var editingScreenTimeout = false
17
    @State private var editingScreenBrightness = false
Bogdan Timofte authored a month ago
18
    @State private var deleteConfirmationVisibility = false
Bogdan Timofte authored 2 months ago
19

            
20
    var body: some View {
21
        VStack(spacing: 0) {
22
            if isMacIPadApp {
23
                settingsMacHeader
24
            }
25
            ScrollView {
26
                VStack(spacing: 14) {
27
                    settingsCard(title: "Name", tint: meter.color) {
28
                        HStack {
29
                            Spacer()
30
                            if !editingName {
31
                                Text(meter.name)
32
                                    .foregroundColor(.secondary)
33
                            }
34
                            ChevronView(rotate: $editingName)
35
                        }
36
                        if editingName {
Bogdan Timofte authored 2 months ago
37
                            MeterNameEditorView(editingName: $editingName, newName: meter.name)
Bogdan Timofte authored 2 months ago
38
                        }
39
                    }
40

            
41
                    if meter.operationalState == .dataIsAvailable && meter.supportsManualTemperatureUnitSelection {
Bogdan Timofte authored a month ago
42
                    settingsCard(
43
                        title: "Meter Temperature Unit",
44
                        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.",
45
                        tint: .orange
46
                    ) {
Bogdan Timofte authored 2 months ago
47
                            Picker("", selection: $meter.tc66TemperatureUnitPreference) {
48
                                ForEach(TemperatureUnitPreference.allCases) { unit in
49
                                    Text(unit.title).tag(unit)
50
                                }
51
                            }
52
                            .pickerStyle(SegmentedPickerStyle())
53
                        }
54
                    }
55

            
Bogdan Timofte authored 2 months ago
56
                    if meter.operationalState == .dataIsAvailable && meter.model == .TC66C {
Bogdan Timofte authored a month ago
57
                        settingsCard(
58
                            title: "Screen Reporting",
59
                            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.",
60
                            tint: .orange
61
                        ) {
Bogdan Timofte authored 2 months ago
62
                            MeterInfoRowView(label: "Current Screen", value: "Not Reported")
Bogdan Timofte authored 2 months ago
63
                        }
64
                    }
65

            
Bogdan Timofte authored 2 months ago
66
                    if meter.operationalState == .dataIsAvailable {
67
                        settingsCard(
68
                            title: meter.reportsCurrentScreenIndex ? "Screen Controls" : "Page Controls",
Bogdan Timofte authored a month ago
69
                            infoMessage: meter.reportsCurrentScreenIndex
70
                                ? "Use these controls when you want to change the screen shown on the device without crowding the main meter view."
71
                                : "Use these controls when you want to switch device pages without crowding the main meter view.",
Bogdan Timofte authored 2 months ago
72
                            tint: .indigo
73
                        ) {
Bogdan Timofte authored 2 months ago
74
                            MeterScreenControlsView(showsHeader: false)
Bogdan Timofte authored 2 months ago
75
                        }
76
                    }
77

            
78
                    if meter.operationalState == .dataIsAvailable && meter.supportsUMSettings {
79
                        settingsCard(title: "Screen Timeout", tint: .purple) {
80
                            HStack {
81
                                Spacer()
82
                                if !editingScreenTimeout {
83
                                    Text(meter.screenTimeout > 0 ? "\(meter.screenTimeout) Minutes" : "Off")
84
                                        .foregroundColor(.secondary)
85
                                }
86
                                ChevronView(rotate: $editingScreenTimeout)
87
                            }
88
                            if editingScreenTimeout {
Bogdan Timofte authored 2 months ago
89
                                ScreenTimeoutEditorView()
Bogdan Timofte authored 2 months ago
90
                            }
91
                        }
92

            
93
                        settingsCard(title: "Screen Brightness", tint: .yellow) {
94
                            HStack {
95
                                Spacer()
96
                                if !editingScreenBrightness {
97
                                    Text("\(meter.screenBrightness)")
98
                                        .foregroundColor(.secondary)
99
                                }
100
                                ChevronView(rotate: $editingScreenBrightness)
101
                            }
102
                            if editingScreenBrightness {
Bogdan Timofte authored 2 months ago
103
                                ScreenBrightnessEditorView()
Bogdan Timofte authored 2 months ago
104
                            }
105
                        }
106
                    }
Bogdan Timofte authored a month ago
107

            
Bogdan Timofte authored a month ago
108
                    settingsCard(
109
                        title: "Danger Zone",
110
                        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.",
111
                        tint: .red
112
                    ) {
Bogdan Timofte authored a month ago
113
                        Button("Delete Meter") {
114
                            deleteConfirmationVisibility = true
115
                        }
116
                        .frame(maxWidth: .infinity)
117
                        .padding(.vertical, 10)
118
                        .meterCard(tint: .red, fillOpacity: 0.16, strokeOpacity: 0.22, cornerRadius: 14)
119
                        .buttonStyle(.plain)
120
                    }
Bogdan Timofte authored 2 months ago
121
                }
122
                .padding()
123
            }
124
            .background(
125
                LinearGradient(
126
                    colors: [meter.color.opacity(0.14), Color.clear],
127
                    startPoint: .topLeading,
128
                    endPoint: .bottomTrailing
129
            )
Bogdan Timofte authored a month ago
130
            .ignoresSafeArea()
131
        )
132
        .alert("Delete Meter?", isPresented: $deleteConfirmationVisibility) {
133
            Button("Delete", role: .destructive) {
134
                if appData.deleteMeter(macAddress: meter.btSerial.macAddress.description) {
135
                    onBackToHome()
136
                }
137
            }
138
            Button("Cancel", role: .cancel) {}
139
        } message: {
140
            Text("This removes the saved meter entry and disconnects the live meter view.")
Bogdan Timofte authored 2 months ago
141
        }
142
    }
Bogdan Timofte authored a month ago
143
    }
Bogdan Timofte authored 2 months ago
144

            
145
    private var settingsMacHeader: some View {
146
        HStack(spacing: 12) {
147
            Button(action: onBackToHome) {
148
                HStack(spacing: 4) {
149
                    Image(systemName: "chevron.left")
150
                        .font(.body.weight(.semibold))
151
                    Text("Back")
152
                }
153
                .foregroundColor(.accentColor)
154
            }
155
            .buttonStyle(.plain)
156

            
157
            Text("Meter Settings")
158
                .font(.headline)
159
                .lineLimit(1)
160

            
161
            Spacer()
162

            
163
            if meter.operationalState > .notPresent {
164
                RSSIView(RSSI: meter.btSerial.averageRSSI)
165
                    .frame(width: 18, height: 18)
166
            }
167
        }
168
        .padding(.horizontal, 16)
169
        .padding(.vertical, 10)
170
        .background(
171
            Rectangle()
172
                .fill(.ultraThinMaterial)
173
                .ignoresSafeArea(edges: .top)
174
        )
175
        .overlay(alignment: .bottom) {
176
            Rectangle()
177
                .fill(Color.secondary.opacity(0.12))
178
                .frame(height: 1)
179
        }
180
    }
181

            
182
    private func settingsCard<Content: View>(
183
        title: String,
Bogdan Timofte authored a month ago
184
        infoMessage: String? = nil,
Bogdan Timofte authored 2 months ago
185
        tint: Color,
186
        @ViewBuilder content: () -> Content
187
    ) -> some View {
188
        VStack(alignment: .leading, spacing: 12) {
Bogdan Timofte authored a month ago
189
            HStack(spacing: 8) {
190
                Text(title)
191
                    .font(.headline)
192
                if let infoMessage {
193
                    ContextInfoButton(title: title, message: infoMessage)
194
                }
195
            }
Bogdan Timofte authored 2 months ago
196
            content()
197
        }
198
        .padding(18)
199
        .meterCard(tint: tint, fillOpacity: 0.18, strokeOpacity: 0.24)
200
    }
201
}