1 contributor
//
// BatteryCheckpointEditorSheetView.swift
// USB Meter
//
// Created by Codex on 10/04/2026.
//
import SwiftUI
struct BatteryCheckpointEditorSheetView: View {
@EnvironmentObject private var appData: AppData
@EnvironmentObject private var meter: Meter
@Environment(\.dismiss) private var dismiss
@State private var batteryPercent = ""
@State private var label = ""
@State private var confirmationWarning: BatteryCheckpointPlausibilityWarning?
private var activeSession: ChargeSessionSummary? {
appData.activeChargeSessionSummary(for: meter.btSerial.macAddress.description)
}
private var plausibilityWarning: BatteryCheckpointPlausibilityWarning? {
guard let percent = Double(batteryPercent),
let activeSession else {
return nil
}
return appData.batteryCheckpointPlausibilityWarning(percent: percent, for: activeSession.id)
}
var body: some View {
NavigationView {
Form {
Section(
header: ContextInfoHeader(
title: "Checkpoint",
message: "The checkpoint is stored on the active charge session and later used for capacity estimation and the typical charge curve."
)
) {
TextField("Battery %", text: $batteryPercent)
.keyboardType(.decimalPad)
TextField("Label (optional)", text: $label)
}
if let plausibilityWarning {
Section(header: Text(plausibilityWarning.title)) {
Text(plausibilityWarning.message)
.font(.footnote)
.foregroundColor(.orange)
}
}
}
.navigationTitle("Battery Checkpoint")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") {
dismiss()
}
}
ToolbarItem(placement: .confirmationAction) {
Button("Save") {
saveCheckpoint()
}
.disabled(
(Double(batteryPercent) ?? -1) < 0
|| (Double(batteryPercent) ?? 101) > 100
|| appData.activeChargeSessionSummary(for: meter.btSerial.macAddress.description) == nil
)
}
}
}
.navigationViewStyle(StackNavigationViewStyle())
.alert(item: $confirmationWarning) { warning in
Alert(
title: Text(warning.title),
message: Text(warning.message),
primaryButton: .destructive(Text("Save Anyway")) {
saveCheckpoint(forceOverride: true)
},
secondaryButton: .cancel()
)
}
}
private func saveCheckpoint(forceOverride: Bool = false) {
guard let percent = Double(batteryPercent) else {
return
}
if !forceOverride, let plausibilityWarning {
confirmationWarning = plausibilityWarning
return
}
let didSave = appData.addBatteryCheckpoint(
percent: percent,
label: label,
for: meter
)
if didSave {
dismiss()
}
}
}