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

            
8
import SwiftUI
9

            
10
struct SidebarChargedDevicesSectionView: View {
11
    let title: String
12
    let chargedDevices: [ChargedDeviceSummary]
13
    let emptyStateText: String
14
    let tint: Color
15
    let onAdd: () -> Void
16

            
17
    var body: some View {
18
        Section(header: headerView) {
19
            if chargedDevices.isEmpty {
20
                Text(emptyStateText)
21
                    .font(.footnote)
22
                    .foregroundColor(.secondary)
23
                    .frame(maxWidth: .infinity, alignment: .leading)
24
                    .padding(18)
25
                    .meterCard(tint: tint, fillOpacity: 0.12, strokeOpacity: 0.18)
26
            } else {
27
                ForEach(chargedDevices) { chargedDevice in
28
                    NavigationLink(destination: ChargedDeviceDetailView(chargedDeviceID: chargedDevice.id)) {
29
                        ChargedDeviceSidebarCardView(chargedDevice: chargedDevice)
30
                    }
31
                    .buttonStyle(.plain)
32
                }
33
            }
34
        }
35
    }
36

            
37
    private var headerView: some View {
38
        HStack(alignment: .firstTextBaseline, spacing: 10) {
39
            Text(title)
40
                .font(.headline)
41
            Spacer()
42
            Button(action: onAdd) {
43
                Image(systemName: "plus.circle.fill")
44
                    .font(.body.weight(.semibold))
45
                    .foregroundColor(tint)
46
            }
47
            .buttonStyle(.plain)
48
            Text("\(chargedDevices.count)")
49
                .font(.caption.weight(.bold))
50
                .padding(.horizontal, 10)
51
                .padding(.vertical, 6)
52
                .meterCard(tint: tint, fillOpacity: 0.18, strokeOpacity: 0.24, cornerRadius: 999)
53
        }
54
    }
55
}
56

            
57
private struct ChargedDeviceSidebarCardView: View {
58
    let chargedDevice: ChargedDeviceSummary
59

            
60
    var body: some View {
61
        HStack(alignment: .top, spacing: 12) {
62
            ChargedDeviceQRCodeView(qrIdentifier: chargedDevice.qrIdentifier, side: 54)
63

            
64
            VStack(alignment: .leading, spacing: 6) {
65
                HStack {
Bogdan Timofte authored a month ago
66
                    ChargedDeviceIdentityLabelView(
67
                        chargedDevice: chargedDevice,
68
                        iconPointSize: 17
69
                    )
70
                    .font(.headline)
Bogdan Timofte authored a month ago
71
                    if chargedDevice.activeSession != nil {
72
                        Spacer()
73
                        Text("Live")
74
                            .font(.caption.weight(.bold))
75
                            .foregroundColor(.green)
76
                    }
77
                }
78

            
Bogdan Timofte authored a month ago
79
                Text(chargedDevice.identityTitle)
Bogdan Timofte authored a month ago
80
                    .font(.caption.weight(.semibold))
81
                    .foregroundColor(.secondary)
82

            
Bogdan Timofte authored a month ago
83
                if chargedDevice.isCharger {
84
                    if let chargerMaximumPowerWatts = chargedDevice.chargerMaximumPowerWatts {
85
                        Text("Max power: \(chargerMaximumPowerWatts.format(decimalDigits: 2)) W")
86
                            .font(.caption2)
87
                            .foregroundColor(.secondary)
88
                    } else {
89
                        Text("Wireless charger")
90
                            .font(.caption2)
91
                            .foregroundColor(.secondary)
92
                    }
Bogdan Timofte authored a month ago
93
                } else {
Bogdan Timofte authored a month ago
94
                    Text(chargedDevice.supportedChargingModes.map(\.title).joined(separator: " + "))
Bogdan Timofte authored a month ago
95
                        .font(.caption2)
96
                        .foregroundColor(.secondary)
Bogdan Timofte authored a month ago
97

            
98
                    if let estimatedCapacityWh = chargedDevice.estimatedBatteryCapacityWh {
99
                        Text("Capacity: \(estimatedCapacityWh.format(decimalDigits: 2)) Wh")
100
                            .font(.caption2)
101
                            .foregroundColor(.secondary)
102
                    } else {
103
                        Text("Capacity: learning")
104
                            .font(.caption2)
105
                            .foregroundColor(.secondary)
106
                    }
Bogdan Timofte authored a month ago
107
                }
108
            }
109
        }
110
        .padding(.vertical, 4)
111
    }
112
}