USB-Meter / USB Meter / Views / ChargedDevices / BatteryCheckpointEditorSheetView.swift
Newer Older
105 lines | 3.581kb
Bogdan Timofte authored a month ago
1
//
2
//  BatteryCheckpointEditorSheetView.swift
3
//  USB Meter
4
//
5
//  Created by Codex on 10/04/2026.
6
//
7

            
8
import SwiftUI
9

            
10
struct BatteryCheckpointEditorSheetView: View {
11
    @EnvironmentObject private var appData: AppData
12
    @EnvironmentObject private var meter: Meter
13
    @Environment(\.dismiss) private var dismiss
14

            
15
    @State private var batteryPercent = ""
16
    @State private var label = ""
Bogdan Timofte authored a month ago
17
    @State private var confirmationWarning: BatteryCheckpointPlausibilityWarning?
18

            
19
    private var activeSession: ChargeSessionSummary? {
20
        appData.activeChargeSessionSummary(for: meter.btSerial.macAddress.description)
21
    }
22

            
23
    private var plausibilityWarning: BatteryCheckpointPlausibilityWarning? {
24
        guard let percent = Double(batteryPercent),
25
              let activeSession else {
26
            return nil
27
        }
28
        return appData.batteryCheckpointPlausibilityWarning(percent: percent, for: activeSession.id)
29
    }
Bogdan Timofte authored a month ago
30

            
31
    var body: some View {
32
        NavigationView {
33
            Form {
Bogdan Timofte authored a month ago
34
                Section(
35
                    header: ContextInfoHeader(
36
                        title: "Checkpoint",
37
                        message: "The checkpoint is stored on the active charge session and later used for capacity estimation and the typical charge curve."
38
                    )
39
                ) {
Bogdan Timofte authored a month ago
40
                    TextField("Battery %", text: $batteryPercent)
41
                        .keyboardType(.decimalPad)
42
                    TextField("Label (optional)", text: $label)
43
                }
44

            
Bogdan Timofte authored a month ago
45
                if let plausibilityWarning {
46
                    Section(header: Text(plausibilityWarning.title)) {
47
                        Text(plausibilityWarning.message)
48
                            .font(.footnote)
49
                            .foregroundColor(.orange)
50
                    }
Bogdan Timofte authored a month ago
51
                }
52
            }
53
            .navigationTitle("Battery Checkpoint")
54
            .navigationBarTitleDisplayMode(.inline)
55
            .toolbar {
56
                ToolbarItem(placement: .cancellationAction) {
57
                    Button("Cancel") {
58
                        dismiss()
59
                    }
60
                }
61
                ToolbarItem(placement: .confirmationAction) {
62
                    Button("Save") {
Bogdan Timofte authored a month ago
63
                        saveCheckpoint()
Bogdan Timofte authored a month ago
64
                    }
65
                    .disabled(
66
                        (Double(batteryPercent) ?? -1) < 0
67
                            || (Double(batteryPercent) ?? 101) > 100
Bogdan Timofte authored a month ago
68
                            || appData.activeChargeSessionSummary(for: meter.btSerial.macAddress.description) == nil
Bogdan Timofte authored a month ago
69
                    )
70
                }
71
            }
72
        }
73
        .navigationViewStyle(StackNavigationViewStyle())
Bogdan Timofte authored a month ago
74
        .alert(item: $confirmationWarning) { warning in
75
            Alert(
76
                title: Text(warning.title),
77
                message: Text(warning.message),
78
                primaryButton: .destructive(Text("Save Anyway")) {
79
                    saveCheckpoint(forceOverride: true)
80
                },
81
                secondaryButton: .cancel()
82
            )
83
        }
84
    }
85

            
86
    private func saveCheckpoint(forceOverride: Bool = false) {
87
        guard let percent = Double(batteryPercent) else {
88
            return
89
        }
90

            
91
        if !forceOverride, let plausibilityWarning {
92
            confirmationWarning = plausibilityWarning
93
            return
94
        }
95

            
96
        let didSave = appData.addBatteryCheckpoint(
97
            percent: percent,
98
            label: label,
99
            for: meter
100
        )
101
        if didSave {
102
            dismiss()
103
        }
Bogdan Timofte authored a month ago
104
    }
105
}