Showing 10 changed files with 48 additions and 266 deletions
+4 -57
USB Meter/Model/AppData.swift
@@ -242,37 +242,6 @@ final class AppData : ObservableObject {
242 242
         }
243 243
     }
244 244
 
245
-    func currentChargedDeviceSummary(for meterMACAddress: String) -> ChargedDeviceSummary? {
246
-        let normalizedMAC = meterMACAddress.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
247
-
248
-        if let activeSession = cachedActiveChargeSessionSummary(for: normalizedMAC),
249
-           let liveDevice = chargedDevices.first(where: {
250
-               $0.id == activeSession.chargedDeviceID && $0.isCharger == false
251
-           }) {
252
-            return liveDevice
253
-        }
254
-
255
-        return chargedDevices.first(where: {
256
-            $0.isCharger == false && $0.lastAssociatedMeterMAC == normalizedMAC
257
-        })
258
-    }
259
-
260
-    func currentChargerSummary(for meterMACAddress: String) -> ChargedDeviceSummary? {
261
-        let normalizedMAC = meterMACAddress.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
262
-
263
-        if let activeSession = cachedActiveChargeSessionSummary(for: normalizedMAC),
264
-           let chargerID = activeSession.chargerID,
265
-           let liveCharger = chargedDevices.first(where: {
266
-               $0.id == chargerID && $0.isCharger
267
-           }) {
268
-            return liveCharger
269
-        }
270
-
271
-        return chargedDevices.first(where: {
272
-            $0.isCharger && $0.lastAssociatedMeterMAC == normalizedMAC
273
-        })
274
-    }
275
-
276 245
     func activeChargeSessionSummary(for meterMACAddress: String) -> ChargeSessionSummary? {
277 246
         let normalizedMAC = Self.normalizedMACAddress(meterMACAddress)
278 247
 
@@ -379,8 +348,7 @@ final class AppData : ObservableObject {
379 348
         supportsWirelessCharging: Bool,
380 349
         wirelessChargingProfile: WirelessChargingProfile,
381 350
         configuredCompletionCurrents: [ChargeSessionKind: Double],
382
-        notes: String?,
383
-        meterMACAddress: String?
351
+        notes: String?
384 352
     ) -> Bool {
385 353
         let didSave = chargeInsightsStore?.createDevice(
386 354
             name: name,
@@ -391,8 +359,7 @@ final class AppData : ObservableObject {
391 359
             supportsWirelessCharging: supportsWirelessCharging,
392 360
             wirelessChargingProfile: wirelessChargingProfile,
393 361
             configuredCompletionCurrents: configuredCompletionCurrents,
394
-            notes: notes,
395
-            assignTo: meterMACAddress
362
+            notes: notes
396 363
         ) ?? false
397 364
 
398 365
         if didSave {
@@ -406,14 +373,12 @@ final class AppData : ObservableObject {
406 373
     func createCharger(
407 374
         name: String,
408 375
         chargerType: ChargerType,
409
-        notes: String?,
410
-        meterMACAddress: String?
376
+        notes: String?
411 377
     ) -> Bool {
412 378
         let didSave = chargeInsightsStore?.createCharger(
413 379
             name: name,
414 380
             chargerType: chargerType,
415
-            notes: notes,
416
-            assignTo: meterMACAddress
381
+            notes: notes
417 382
         ) ?? false
418 383
 
419 384
         if didSave {
@@ -477,24 +442,6 @@ final class AppData : ObservableObject {
477 442
         return didSave
478 443
     }
479 444
 
480
-    @discardableResult
481
-    func assignChargedDevice(_ chargedDeviceID: UUID, to meterMACAddress: String) -> Bool {
482
-        let didSave = chargeInsightsStore?.assignChargedDevice(id: chargedDeviceID, to: meterMACAddress) ?? false
483
-        if didSave {
484
-            reloadChargedDevices()
485
-        }
486
-        return didSave
487
-    }
488
-
489
-    @discardableResult
490
-    func assignCharger(_ chargerID: UUID, to meterMACAddress: String) -> Bool {
491
-        let didSave = chargeInsightsStore?.assignCharger(id: chargerID, to: meterMACAddress) ?? false
492
-        if didSave {
493
-            reloadChargedDevices()
494
-        }
495
-        return didSave
496
-    }
497
-
498 445
     func restoreChargeMonitoringStateIfNeeded(for meter: Meter) {
499 446
         guard let activeSession = activeChargeSessionSummary(for: meter.btSerial.macAddress.description) else {
500 447
             return
+2 -123
USB Meter/Model/ChargeInsightsStore.swift
@@ -16,20 +16,6 @@ final class ChargeInsightsStore {
16 16
         static let chargeSessionSample = "ChargeSessionSample"
17 17
     }
18 18
 
19
-    private enum MeterAssignmentKind {
20
-        case chargedDevice
21
-        case charger
22
-
23
-        var expectsChargerClass: Bool {
24
-            switch self {
25
-            case .chargedDevice:
26
-                return false
27
-            case .charger:
28
-                return true
29
-            }
30
-        }
31
-    }
32
-
33 19
     private static let maximumChargeSessionDuration: TimeInterval = 12 * 60 * 60
34 20
     private static let persistedSamplesPerHour = 360
35 21
     private static let aggregatedSampleBucketDuration = 3600.0 / Double(persistedSamplesPerHour)
@@ -190,8 +176,7 @@ final class ChargeInsightsStore {
190 176
         supportsWirelessCharging: Bool,
191 177
         wirelessChargingProfile: WirelessChargingProfile,
192 178
         configuredCompletionCurrents: [ChargeSessionKind: Double],
193
-        notes: String?,
194
-        assignTo meterMACAddress: String?
179
+        notes: String?
195 180
     ) -> Bool {
196 181
         guard deviceClass.kind == .device else { return false }
197 182
         let normalizedName = normalizedText(name)
@@ -226,7 +211,6 @@ final class ChargeInsightsStore {
226 211
             object.setValue(legacyConfiguredCompletionCurrent(for: configuredCompletionCurrents, chargingTransportMode: .wireless), forKey: "wirelessChargeCompletionCurrentAmps")
227 212
             object.setValue(normalizedOptionalText(notes), forKey: "notes")
228 213
             object.setValue(generateQRIdentifier(), forKey: "qrIdentifier")
229
-            object.setValue(normalizedOptionalText(meterMACAddress), forKey: "lastAssociatedMeterMAC")
230 214
             object.setValue(now, forKey: "createdAt")
231 215
             object.setValue(now, forKey: "updatedAt")
232 216
             didSave = saveContext()
@@ -238,8 +222,7 @@ final class ChargeInsightsStore {
238 222
     func createCharger(
239 223
         name: String,
240 224
         chargerType: ChargerType,
241
-        notes: String?,
242
-        assignTo meterMACAddress: String?
225
+        notes: String?
243 226
     ) -> Bool {
244 227
         let normalizedName = normalizedText(name)
245 228
         guard !normalizedName.isEmpty else { return false }
@@ -269,7 +252,6 @@ final class ChargeInsightsStore {
269 252
             object.setValue(nil, forKey: "wirelessChargeCompletionCurrentAmps")
270 253
             object.setValue(normalizedOptionalText(notes), forKey: "notes")
271 254
             object.setValue(generateQRIdentifier(), forKey: "qrIdentifier")
272
-            object.setValue(normalizedOptionalText(meterMACAddress), forKey: "lastAssociatedMeterMAC")
273 255
             object.setValue(now, forKey: "createdAt")
274 256
             object.setValue(now, forKey: "updatedAt")
275 257
             didSave = saveContext()
@@ -425,67 +407,6 @@ final class ChargeInsightsStore {
425 407
         return didSave
426 408
     }
427 409
 
428
-    @discardableResult
429
-    func assignChargedDevice(id: UUID, to meterMACAddress: String) -> Bool {
430
-        assign(itemWithID: id, to: meterMACAddress, kind: .chargedDevice)
431
-    }
432
-
433
-    @discardableResult
434
-    func assignCharger(id: UUID, to meterMACAddress: String) -> Bool {
435
-        assign(itemWithID: id, to: meterMACAddress, kind: .charger)
436
-    }
437
-
438
-    @discardableResult
439
-    private func assign(
440
-        itemWithID id: UUID,
441
-        to meterMACAddress: String,
442
-        kind: MeterAssignmentKind
443
-    ) -> Bool {
444
-        let normalizedMAC = normalizedMACAddress(meterMACAddress)
445
-        guard !normalizedMAC.isEmpty else { return false }
446
-
447
-        var didSave = false
448
-        context.performAndWait {
449
-            guard let object = fetchChargedDeviceObject(id: id.uuidString) else {
450
-                return
451
-            }
452
-
453
-            let isCharger = ChargedDeviceClass(rawValue: stringValue(object, key: "deviceClassRawValue") ?? "") == .charger
454
-            guard isCharger == kind.expectsChargerClass else {
455
-                return
456
-            }
457
-
458
-            let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargedDevice)
459
-            request.predicate = NSPredicate(
460
-                format: "lastAssociatedMeterMAC == %@ AND id != %@",
461
-                normalizedMAC,
462
-                id.uuidString
463
-            )
464
-            let previouslyAssignedDevices = (try? context.fetch(request)) ?? []
465
-            for previousDevice in previouslyAssignedDevices {
466
-                let previousIsCharger = ChargedDeviceClass(rawValue: stringValue(previousDevice, key: "deviceClassRawValue") ?? "") == .charger
467
-                guard previousIsCharger == kind.expectsChargerClass else {
468
-                    continue
469
-                }
470
-                previousDevice.setValue(nil, forKey: "lastAssociatedMeterMAC")
471
-                previousDevice.setValue(Date(), forKey: "updatedAt")
472
-            }
473
-
474
-            object.setValue(normalizedMAC, forKey: "lastAssociatedMeterMAC")
475
-            object.setValue(Date(), forKey: "updatedAt")
476
-
477
-            if kind == .charger,
478
-               let openSession = fetchOpenSessionObject(forMeterMACAddress: normalizedMAC),
479
-               chargingTransportMode(for: openSession) == .wireless {
480
-                openSession.setValue(id.uuidString, forKey: "chargerID")
481
-                openSession.setValue(Date(), forKey: "updatedAt")
482
-            }
483
-
484
-            didSave = saveContext()
485
-        }
486
-        return didSave
487
-    }
488
-
489 410
     @discardableResult
490 411
     func startSession(
491 412
         for snapshot: ChargingMonitorSnapshot,
@@ -1344,7 +1265,6 @@ final class ChargeInsightsStore {
1344 1265
                     wirelessMinimumCurrentAmps: optionalDoubleValue(device, key: "wirelessMinimumCurrentAmps"),
1345 1266
                     wiredEstimatedBatteryCapacityWh: optionalDoubleValue(device, key: "wiredEstimatedBatteryCapacityWh"),
1346 1267
                     wirelessEstimatedBatteryCapacityWh: optionalDoubleValue(device, key: "wirelessEstimatedBatteryCapacityWh"),
1347
-                    lastAssociatedMeterMAC: stringValue(device, key: "lastAssociatedMeterMAC"),
1348 1268
                     createdAt: dateValue(device, key: "createdAt") ?? .distantPast,
1349 1269
                     updatedAt: dateValue(device, key: "updatedAt") ?? .distantPast,
1350 1270
                     sessions: sessionSummaries,
@@ -1370,21 +1290,6 @@ final class ChargeInsightsStore {
1370 1290
         return summaries
1371 1291
     }
1372 1292
 
1373
-    func resolvedChargedDeviceSummary(forMeterMACAddress meterMACAddress: String) -> ChargedDeviceSummary? {
1374
-        let normalizedMAC = normalizedMACAddress(meterMACAddress)
1375
-        guard !normalizedMAC.isEmpty else { return nil }
1376
-
1377
-        let summaries = fetchChargedDeviceSummaries().filter { !$0.isCharger }
1378
-
1379
-        if let activeMatch = summaries.first(where: { summary in
1380
-            summary.activeSession?.meterMACAddress == normalizedMAC
1381
-        }) {
1382
-            return activeMatch
1383
-        }
1384
-
1385
-        return summaries.first(where: { $0.lastAssociatedMeterMAC == normalizedMAC })
1386
-    }
1387
-
1388 1293
     func activeChargeSessionSummary(forMeterMACAddress meterMACAddress: String) -> ChargeSessionSummary? {
1389 1294
         let normalizedMAC = normalizedMACAddress(meterMACAddress)
1390 1295
         guard !normalizedMAC.isEmpty else { return nil }
@@ -1485,8 +1390,6 @@ final class ChargeInsightsStore {
1485 1390
         session.setValue(now, forKey: "createdAt")
1486 1391
         session.setValue(now, forKey: "updatedAt")
1487 1392
 
1488
-        chargedDevice.setValue(snapshot.meterMACAddress, forKey: "lastAssociatedMeterMAC")
1489
-        chargedDevice.setValue(now, forKey: "updatedAt")
1490 1393
         return session
1491 1394
     }
1492 1395
 
@@ -2889,30 +2792,6 @@ final class ChargeInsightsStore {
2889 2792
             }
2890 2793
     }
2891 2794
 
2892
-    private func resolvedDeviceObject(for meterMACAddress: String) -> NSManagedObject? {
2893
-        resolvedAssignedObject(for: meterMACAddress, expectsChargerClass: false)
2894
-    }
2895
-
2896
-    private func resolvedChargerObject(for meterMACAddress: String) -> NSManagedObject? {
2897
-        resolvedAssignedObject(for: meterMACAddress, expectsChargerClass: true)
2898
-    }
2899
-
2900
-    private func resolvedAssignedObject(
2901
-        for meterMACAddress: String,
2902
-        expectsChargerClass: Bool
2903
-    ) -> NSManagedObject? {
2904
-        let normalizedMAC = normalizedMACAddress(meterMACAddress)
2905
-        guard !normalizedMAC.isEmpty else { return nil }
2906
-
2907
-        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargedDevice)
2908
-        request.predicate = NSPredicate(format: "lastAssociatedMeterMAC == %@", normalizedMAC)
2909
-        request.sortDescriptors = [NSSortDescriptor(key: "updatedAt", ascending: false)]
2910
-        let matches = (try? context.fetch(request)) ?? []
2911
-        return matches.first { object in
2912
-            isChargerObject(object) == expectsChargerClass
2913
-        }
2914
-    }
2915
-
2916 2795
     private func isChargerObject(_ object: NSManagedObject) -> Bool {
2917 2796
         ChargedDeviceClass(rawValue: stringValue(object, key: "deviceClassRawValue") ?? "") == .charger
2918 2797
     }
+1 -14
USB Meter/Views/ChargedDevices/Details/ChargedDeviceSettingsView.swift
@@ -48,10 +48,7 @@ struct ChargedDeviceSettingsView: View {
48 48
                     ChargerEditorSheetView(chargedDevice: chargedDevice)
49 49
                         .environmentObject(appData)
50 50
                 } else {
51
-                    ChargedDeviceEditorSheetView(
52
-                        meterMACAddress: nil,
53
-                        chargedDevice: chargedDevice
54
-                    )
51
+                    ChargedDeviceEditorSheetView(chargedDevice: chargedDevice)
55 52
                     .environmentObject(appData)
56 53
                 }
57 54
             }
@@ -336,12 +333,6 @@ struct ChargedDeviceSettingsView: View {
336 333
                     .font(.subheadline.weight(.semibold))
337 334
                     .foregroundColor(.secondary)
338 335
 
339
-                if let meterMAC = chargedDevice.lastAssociatedMeterMAC {
340
-                    Text("Default meter: \(meterMAC)")
341
-                        .font(.caption)
342
-                        .foregroundColor(.secondary)
343
-                }
344
-
345 336
                 Text(chargedDevice.qrIdentifier)
346 337
                     .font(.caption2.monospaced())
347 338
                     .foregroundColor(.secondary)
@@ -364,10 +355,6 @@ struct ChargedDeviceSettingsView: View {
364 355
             MeterInfoRowView(label: "Template", value: chargedDevice.identityTitle)
365 356
             MeterInfoRowView(label: "QR ID", value: chargedDevice.qrIdentifier)
366 357
 
367
-            if let meterMAC = chargedDevice.lastAssociatedMeterMAC {
368
-                MeterInfoRowView(label: "Default Meter", value: meterMAC)
369
-            }
370
-
371 358
             MeterInfoRowView(label: "Created", value: chargedDevice.createdAt.format())
372 359
             MeterInfoRowView(label: "Updated", value: chargedDevice.updatedAt.format())
373 360
 
+1 -5
USB Meter/Views/ChargedDevices/Sheets/Editors/ChargedDeviceEditorSheetView.swift
@@ -11,7 +11,6 @@ struct ChargedDeviceEditorSheetView: View {
11 11
     @EnvironmentObject private var appData: AppData
12 12
     @Environment(\.dismiss) private var dismiss
13 13
 
14
-    let meterMACAddress: String?
15 14
     let chargedDevice: ChargedDeviceSummary?
16 15
 
17 16
     @State private var name: String
@@ -28,11 +27,9 @@ struct ChargedDeviceEditorSheetView: View {
28 27
     let standalone: Bool
29 28
 
30 29
     init(
31
-        meterMACAddress: String?,
32 30
         chargedDevice: ChargedDeviceSummary? = nil,
33 31
         standalone: Bool = true
34 32
     ) {
35
-        self.meterMACAddress = meterMACAddress
36 33
         self.chargedDevice = chargedDevice
37 34
         self.standalone = standalone
38 35
 
@@ -364,8 +361,7 @@ struct ChargedDeviceEditorSheetView: View {
364 361
                 supportsWirelessCharging: supportsWirelessCharging,
365 362
                 wirelessChargingProfile: wirelessChargingProfile,
366 363
                 configuredCompletionCurrents: configuredCompletionCurrents,
367
-                notes: notes,
368
-                meterMACAddress: meterMACAddress
364
+                notes: notes
369 365
             )
370 366
         }
371 367
 
+7 -35
USB Meter/Views/ChargedDevices/Sheets/Library/ChargedDeviceLibrarySheetView.swift
@@ -33,7 +33,6 @@ struct ChargedDeviceLibrarySheetView: View {
33 33
     @EnvironmentObject private var appData: AppData
34 34
     @Environment(\.dismiss) private var dismiss
35 35
 
36
-    let meterMACAddress: String
37 36
     let meterTint: Color
38 37
     let mode: ChargedDeviceLibraryMode
39 38
     /// true = standalone sheet with own NavigationView; false = pushed into parent nav stack
@@ -44,12 +43,10 @@ struct ChargedDeviceLibrarySheetView: View {
44 43
     @State private var pendingDeletion: ChargedDeviceSummary?
45 44
 
46 45
     init(
47
-        meterMACAddress: String,
48 46
         meterTint: Color,
49 47
         mode: ChargedDeviceLibraryMode,
50 48
         standalone: Bool = true
51 49
     ) {
52
-        self.meterMACAddress = meterMACAddress
53 50
         self.meterTint = meterTint
54 51
         self.mode = mode
55 52
         self.standalone = standalone
@@ -81,16 +78,12 @@ struct ChargedDeviceLibrarySheetView: View {
81 78
                 .listRowBackground(Color.clear)
82 79
             } else {
83 80
                 ForEach(displayedChargedDevices) { chargedDevice in
84
-                    Button {
85
-                        select(chargedDevice)
86
-                        dismiss()
87
-                    } label: {
81
+                    NavigationLink(destination: ChargedDeviceSettingsView(chargedDeviceID: chargedDevice.id)) {
88 82
                         ChargedDeviceLibraryRowView(
89 83
                             chargedDevice: chargedDevice,
90
-                            isSelected: chargedDevice.id == selectedDeviceID
84
+                            isSelected: false
91 85
                         )
92 86
                     }
93
-                    .buttonStyle(.plain)
94 87
                     .swipeActions(edge: .trailing, allowsFullSwipe: false) {
95 88
                         Button(role: .destructive) {
96 89
                             pendingDeletion = chargedDevice
@@ -169,10 +162,10 @@ struct ChargedDeviceLibrarySheetView: View {
169 162
     @ViewBuilder
170 163
     private var newEditorSheet: some View {
171 164
         if mode == .charger {
172
-            ChargerEditorSheetView(meterMACAddress: meterMACAddress)
165
+            ChargerEditorSheetView()
173 166
                 .environmentObject(appData)
174 167
         } else {
175
-            ChargedDeviceEditorSheetView(meterMACAddress: meterMACAddress)
168
+            ChargedDeviceEditorSheetView()
176 169
                 .environmentObject(appData)
177 170
         }
178 171
     }
@@ -183,10 +176,7 @@ struct ChargedDeviceLibrarySheetView: View {
183 176
             ChargerEditorSheetView(chargedDevice: chargedDevice)
184 177
                 .environmentObject(appData)
185 178
         } else {
186
-            ChargedDeviceEditorSheetView(
187
-                meterMACAddress: nil,
188
-                chargedDevice: chargedDevice
189
-            )
179
+            ChargedDeviceEditorSheetView(chargedDevice: chargedDevice)
190 180
             .environmentObject(appData)
191 181
         }
192 182
     }
@@ -200,30 +190,12 @@ struct ChargedDeviceLibrarySheetView: View {
200 190
         }
201 191
     }
202 192
 
203
-    private var selectedDeviceID: UUID? {
204
-        switch mode {
205
-        case .device:
206
-            return appData.currentChargedDeviceSummary(for: meterMACAddress)?.id
207
-        case .charger:
208
-            return appData.currentChargerSummary(for: meterMACAddress)?.id
209
-        }
210
-    }
211
-
212 193
     private var emptyStateDescription: String {
213 194
         switch mode {
214 195
         case .device:
215
-            return "Create one here, then select it before or during a charging session. The selected device becomes the default for this meter."
216
-        case .charger:
217
-            return "Create one here, then select it for wireless charging sessions. The selected charger becomes the default wireless source for this meter."
218
-        }
219
-    }
220
-
221
-    private func select(_ chargedDevice: ChargedDeviceSummary) {
222
-        switch mode {
223
-        case .device:
224
-            appData.assignChargedDevice(chargedDevice.id, to: meterMACAddress)
196
+            return "Create one here, then select it explicitly when starting a charging session."
225 197
         case .charger:
226
-            appData.assignCharger(chargedDevice.id, to: meterMACAddress)
198
+            return "Create one here, then select it explicitly for wireless charging sessions or standby measurements."
227 199
         }
228 200
     }
229 201
 }
+1 -5
USB Meter/Views/Chargers/ChargerEditorSheetView.swift
@@ -10,7 +10,6 @@ struct ChargerEditorSheetView: View {
10 10
     @Environment(\.dismiss) private var dismiss
11 11
 
12 12
     let chargedDevice: ChargedDeviceSummary?
13
-    let meterMACAddress: String?
14 13
     /// When false the view omits its own NavigationView (used as a push destination).
15 14
     let standalone: Bool
16 15
 
@@ -20,11 +19,9 @@ struct ChargerEditorSheetView: View {
20 19
 
21 20
     init(
22 21
         chargedDevice: ChargedDeviceSummary? = nil,
23
-        meterMACAddress: String? = nil,
24 22
         standalone: Bool = true
25 23
     ) {
26 24
         self.chargedDevice = chargedDevice
27
-        self.meterMACAddress = meterMACAddress
28 25
         self.standalone = standalone
29 26
         _name = State(initialValue: chargedDevice?.name ?? "")
30 27
         _chargerType = State(initialValue: chargedDevice?.chargerType ?? .genericQi)
@@ -99,8 +96,7 @@ struct ChargerEditorSheetView: View {
99 96
             didSave = appData.createCharger(
100 97
                 name: name,
101 98
                 chargerType: chargerType,
102
-                notes: notesValue,
103
-                meterMACAddress: meterMACAddress
99
+                notes: notesValue
104 100
             )
105 101
         }
106 102
 
+1 -11
USB Meter/Views/Chargers/ChargerStandbyPowerWizardView.swift
@@ -56,7 +56,6 @@ struct ChargerStandbyPowerWizardView: View {
56 56
         .navigationBarTitleDisplayMode(.inline)
57 57
         .sheet(isPresented: $chargerLibraryVisibility) {
58 58
             ChargedDeviceLibrarySheetView(
59
-                meterMACAddress: selectedMeterSummary?.macAddress ?? "",
60 59
                 meterTint: selectedMeter?.color ?? .orange,
61 60
                 mode: .charger
62 61
             )
@@ -86,15 +85,10 @@ struct ChargerStandbyPowerWizardView: View {
86 85
         appData.chargerSummaries
87 86
     }
88 87
 
89
-    private var preferredChargerMeterMACAddress: String? {
90
-        preferredChargerID.flatMap { appData.chargedDeviceSummary(id: $0)?.lastAssociatedMeterMAC }
91
-    }
92
-
93 88
     private var activeSession: ChargerStandbyPowerMonitorSession? {
94 89
         let candidateMACAddresses = [
95 90
             selectedMeterMACAddress ?? "",
96
-            preferredMeterMACAddress ?? "",
97
-            preferredChargerMeterMACAddress ?? ""
91
+            preferredMeterMACAddress ?? ""
98 92
         ]
99 93
         .filter { $0.isEmpty == false }
100 94
 
@@ -118,10 +112,6 @@ struct ChargerStandbyPowerWizardView: View {
118 112
             return liveMeterSummaries.first(where: { $0.macAddress == preferredMeterMACAddress })
119 113
         }
120 114
 
121
-        if let preferredChargerMeterMACAddress {
122
-            return liveMeterSummaries.first(where: { $0.macAddress == preferredChargerMeterMACAddress })
123
-        }
124
-
125 115
         return liveMeterSummaries.count == 1 ? liveMeterSummaries.first : nil
126 116
     }
127 117
 
+25 -8
USB Meter/Views/Meter/Tabs/ChargeRecord/MeterChargeRecordTabView.swift
@@ -80,6 +80,8 @@ struct MeterChargeRecordContentView: View {
80 80
     @State private var initialCheckpoint = ""
81 81
     @State private var showsMeterTotalsInfo = false
82 82
     @State private var activeMode: ActiveMode = .chargeSession
83
+    @State private var draftChargedDeviceID: UUID?
84
+    @State private var draftChargerID: UUID?
83 85
 
84 86
     var body: some View {
85 87
         Group {
@@ -134,7 +136,13 @@ struct MeterChargeRecordContentView: View {
134 136
     }
135 137
 
136 138
     private var selectedChargedDevice: ChargedDeviceSummary? {
137
-        appData.currentChargedDeviceSummary(for: meterMACAddress)
139
+        if let openChargeSession {
140
+            return appData.chargedDeviceSummary(id: openChargeSession.chargedDeviceID)
141
+        }
142
+
143
+        guard let draftChargedDeviceID else { return nil }
144
+        let chargedDevice = appData.chargedDeviceSummary(id: draftChargedDeviceID)
145
+        return chargedDevice?.isCharger == false ? chargedDevice : nil
138 146
     }
139 147
 
140 148
     private var availableChargedDevices: [ChargedDeviceSummary] {
@@ -143,16 +151,26 @@ struct MeterChargeRecordContentView: View {
143 151
 
144 152
     private var selectedChargedDeviceID: Binding<UUID?> {
145 153
         Binding(
146
-            get: { selectedChargedDevice?.id },
154
+            get: { openChargeSession?.chargedDeviceID ?? draftChargedDeviceID },
147 155
             set: { newValue in
148
-                guard let newValue else { return }
149
-                _ = appData.assignChargedDevice(newValue, to: meterMACAddress)
156
+                draftChargedDeviceID = newValue
157
+                if newValue == nil {
158
+                    draftChargingTransportMode = nil
159
+                    draftChargingStateMode = nil
160
+                }
150 161
             }
151 162
         )
152 163
     }
153 164
 
154 165
     private var selectedCharger: ChargedDeviceSummary? {
155
-        appData.currentChargerSummary(for: meterMACAddress)
166
+        if let openChargeSession,
167
+           let chargerID = openChargeSession.chargerID {
168
+            return appData.chargedDeviceSummary(id: chargerID)
169
+        }
170
+
171
+        guard let draftChargerID else { return nil }
172
+        let charger = appData.chargedDeviceSummary(id: draftChargerID)
173
+        return charger?.isCharger == true ? charger : nil
156 174
     }
157 175
 
158 176
     private var availableChargers: [ChargedDeviceSummary] {
@@ -161,10 +179,9 @@ struct MeterChargeRecordContentView: View {
161 179
 
162 180
     private var selectedChargerID: Binding<UUID?> {
163 181
         Binding(
164
-            get: { selectedCharger?.id },
182
+            get: { openChargeSession?.chargerID ?? draftChargerID },
165 183
             set: { newValue in
166
-                guard let newValue else { return }
167
-                _ = appData.assignCharger(newValue, to: meterMACAddress)
184
+                draftChargerID = newValue
168 185
             }
169 186
         )
170 187
     }
+5 -5
USB Meter/Views/Sidebar/SidebarChargedDeviceLibraryView.swift
@@ -110,10 +110,10 @@ struct SidebarChargedDeviceLibraryView: View {
110 110
     @ViewBuilder
111 111
     private var newEditorSheet: some View {
112 112
         if mode == .charger {
113
-            ChargerEditorSheetView(meterMACAddress: nil)
113
+            ChargerEditorSheetView()
114 114
                 .environmentObject(appData)
115 115
         } else {
116
-            ChargedDeviceEditorSheetView(meterMACAddress: nil)
116
+            ChargedDeviceEditorSheetView()
117 117
                 .environmentObject(appData)
118 118
         }
119 119
     }
@@ -124,7 +124,7 @@ struct SidebarChargedDeviceLibraryView: View {
124 124
             ChargerEditorSheetView(chargedDevice: device)
125 125
                 .environmentObject(appData)
126 126
         } else {
127
-            ChargedDeviceEditorSheetView(meterMACAddress: nil, chargedDevice: device)
127
+            ChargedDeviceEditorSheetView(chargedDevice: device)
128 128
                 .environmentObject(appData)
129 129
         }
130 130
     }
@@ -146,8 +146,8 @@ struct SidebarChargedDeviceLibraryView: View {
146 146
 
147 147
     private var emptyStateDescription: String {
148 148
         mode == .device
149
-            ? "Create one here, then select it before or during a charging session. The selected device becomes the default for this meter."
150
-            : "Create one here, then select it for wireless charging sessions. The selected charger becomes the default wireless source for this meter."
149
+            ? "Create one here, then select it explicitly when starting a charging session."
150
+            : "Create one here, then select it explicitly for wireless charging sessions or standby measurements."
151 151
     }
152 152
 
153 153
     private func deletePendingDevice() {
+1 -3
USB Meter/Views/Sidebar/SidebarView.swift
@@ -61,9 +61,7 @@ struct SidebarView: View {
61 61
                 MeterEditorSheetView()
62 62
                     .environmentObject(appData)
63 63
             case .device:
64
-                ChargedDeviceEditorSheetView(
65
-                    meterMACAddress: nil
66
-                )
64
+                ChargedDeviceEditorSheetView()
67 65
                 .environmentObject(appData)
68 66
             case .charger:
69 67
                 ChargerEditorSheetView()