// // RecordingView.swift // USB Meter // // Created by Bogdan Timofte on 09/03/2020. // Copyright © 2020 Bogdan Timofte. All rights reserved. // import SwiftUI struct RecordingView: View { @Binding var visibility: Bool @EnvironmentObject private var usbMeter: Meter var body: some View { NavigationView { ScrollView { VStack(spacing: 16) { VStack(alignment: .leading, spacing: 8) { HStack { Text("Charge Record") .font(.system(.title3, design: .rounded).weight(.bold)) Spacer() Text(usbMeter.chargeRecordStatusText) .font(.caption.weight(.bold)) .foregroundColor(usbMeter.chargeRecordStatusColor) .padding(.horizontal, 10) .padding(.vertical, 6) .meterCard( tint: usbMeter.chargeRecordStatusColor, fillOpacity: 0.18, strokeOpacity: 0.24, cornerRadius: 999 ) } Text("App-side charge accumulation based on the stop-threshold workflow.") .font(.footnote) .foregroundColor(.secondary) } .frame(maxWidth: .infinity) .padding(18) .meterCard(tint: .pink, fillOpacity: 0.18, strokeOpacity: 0.24) HStack(alignment: .top) { VStack(alignment: .leading, spacing: 10) { Text("Capacity") Text("Energy") Text("Duration") Text("Stop Threshold") } Spacer() VStack(alignment: .trailing, spacing: 10) { Text("\(usbMeter.chargeRecordAH.format(decimalDigits: 3)) Ah") Text("\(usbMeter.chargeRecordWH.format(decimalDigits: 3)) Wh") Text(usbMeter.chargeRecordDurationDescription) Text("\(usbMeter.chargeRecordStopThreshold.format(decimalDigits: 2)) A") } .monospacedDigit() } .font(.footnote.weight(.semibold)) .padding(18) .meterCard(tint: .pink, fillOpacity: 0.14, strokeOpacity: 0.20) if usbMeter.chargeRecordTimeRange != nil { VStack(alignment: .leading, spacing: 12) { HStack { Text("Charge Curve") .font(.headline) Spacer() Button("Reset Graph") { usbMeter.resetChargeRecordGraph() } .foregroundColor(.red) } MeasurementChartView(timeRange: usbMeter.chargeRecordTimeRange) .environmentObject(usbMeter.measurements) .frame(minHeight: 220) Text("Reset Graph clears the current charge-record session and removes older shared samples that are no longer needed for this curve.") .font(.footnote) .foregroundColor(.secondary) } .padding(18) .meterCard(tint: .blue, fillOpacity: 0.14, strokeOpacity: 0.20) } VStack(alignment: .leading, spacing: 12) { Text("Stop Threshold") .font(.headline) Slider(value: $usbMeter.chargeRecordStopThreshold, in: 0...0.30, step: 0.01) Text("The app starts accumulating when current rises above this threshold and stops when it falls back to or below it.") .font(.footnote) .foregroundColor(.secondary) Button("Reset") { usbMeter.resetChargeRecord() } .frame(maxWidth: .infinity) .padding(.vertical, 10) .meterCard(tint: .orange, fillOpacity: 0.16, strokeOpacity: 0.22, cornerRadius: 14) .buttonStyle(.plain) } .padding(18) .meterCard(tint: .orange, fillOpacity: 0.14, strokeOpacity: 0.20) if usbMeter.supportsDataGroupCommands || usbMeter.recordedAH > 0 || usbMeter.recordedWH > 0 || usbMeter.recordingDuration > 0 { VStack(alignment: .leading, spacing: 12) { Text("Meter Totals") .font(.headline) HStack(alignment: .top) { VStack(alignment: .leading, spacing: 10) { Text("Capacity") Text("Energy") Text("Duration") Text("Meter Threshold") } Spacer() VStack(alignment: .trailing, spacing: 10) { Text("\(usbMeter.recordedAH.format(decimalDigits: 3)) Ah") Text("\(usbMeter.recordedWH.format(decimalDigits: 3)) Wh") Text(usbMeter.recordingDurationDescription) if usbMeter.supportsRecordingThreshold { Text("\(usbMeter.recordingTreshold.format(decimalDigits: 2)) A") } else { Text("Read-only") } } .monospacedDigit() } .font(.footnote.weight(.semibold)) Text("These values are reported by the meter for the active data group.") .font(.footnote) .foregroundColor(.secondary) if usbMeter.supportsDataGroupCommands { Button("Reset Active Group") { usbMeter.clear() } .frame(maxWidth: .infinity) .padding(.vertical, 10) .meterCard(tint: .red, fillOpacity: 0.16, strokeOpacity: 0.22, cornerRadius: 14) .buttonStyle(.plain) } } .padding(18) .meterCard(tint: .teal, fillOpacity: 0.14, strokeOpacity: 0.20) } } .padding() } .background( LinearGradient( colors: [.pink.opacity(0.14), Color.clear], startPoint: .topLeading, endPoint: .bottomTrailing ) .ignoresSafeArea() ) .navigationBarTitle("Charge Record", displayMode: .inline) .navigationBarItems(trailing: Button("Done") { visibility.toggle() }) } .navigationViewStyle(StackNavigationViewStyle()) } } struct RecordingView_Previews: PreviewProvider { static var previews: some View { RecordingView(visibility: .constant(true)) } }