Files
VanAligneiOS/CamperMonitor/CamperMonitorApp.swift
fototeddyandClaude Sonnet 5 9a3b5cb472 Fix device signing/companion ID, duplicate-device crash, background updates, and add level bubble to Live Activity
- Assign the shared development team to the widget extension and watch
  complication targets, and correct the watch app's companion bundle
  identifier so on-device installs succeed after the bundle ID rename
  to de.s0.fototeddy.VanAligneiOS.
- Guard against two ConfiguredDevices sharing a peripheralID (e.g. a
  double-tapped "Sichern"), which crashed BluetoothManager's
  Dictionary(uniqueKeysWithValues:) on launch.
- Keep Bluetooth running in the background while a Live Activity is
  active, so lock screen/CarPlay keep receiving fresh readings instead
  of freezing at the last value before backgrounding.
- Render the actual bubble-level graphic (not just a static icon) in
  the Live Activity's lock screen view and expanded Dynamic Island.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 23:50:08 +02:00

57 lines
2.3 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import SwiftUI
@main
struct CamperMonitorApp: App {
@State private var store: DeviceStore
@State private var bluetooth: BluetoothManager
@State private var watch: PhoneWatchLink
@State private var levelActivity: LevelActivityManager
@Environment(\.scenePhase) private var scenePhase
init() {
let store = DeviceStore()
let bluetooth = BluetoothManager(store: store)
let levelActivity = LevelActivityManager()
bluetooth.activityManager = levelActivity
_store = State(initialValue: store)
_bluetooth = State(initialValue: bluetooth)
_watch = State(initialValue: PhoneWatchLink(store: store, bluetooth: bluetooth))
_levelActivity = State(initialValue: levelActivity)
}
var body: some Scene {
WindowGroup {
DashboardView()
.environment(store)
.environment(bluetooth)
.environment(watch)
.environment(levelActivity)
.task { watch.activate() }
}
.onChange(of: scenePhase) { _, phase in
// Im Hintergrund darf ohne Service-Filter ohnehin nicht gescannt
// werden, also Funk sparen und beim Zurückkommen neu starten.
//
// Ausnahme: Solange jemand auf die Uhr schaut, läuft es weiter. Beim
// Rangieren liegt das iPhone in der Halterung mit dunklem Bildschirm
// hörte das Funkgerät dann auf, wäre die Anzeige am Handgelenk
// genau dann tot, wenn sie gebraucht wird. Die verbundenen Geräte
// (Neigungsmesser, BMS, Kühlbox) liefern im Hintergrund weiter; die
// Victron-Werbedaten nicht, dafür müsste ohne Filter gesucht werden.
watch.isAppInBackground = phase != .active
switch phase {
case .active:
bluetooth.start()
case .background:
// Läuft gerade eine Live Activity, muss der Neigungsmesser
// auch mit dunklem Bildschirm weiter Werte liefern sonst
// friert die Anzeige auf Sperrbildschirm und CarPlay beim
// ersten Wegdrücken der App ein.
if !watch.wantsLiveUpdates && !levelActivity.isActive { bluetooth.stop() }
default:
break
}
}
}
}