49 lines
2.0 KiB
Swift
49 lines
2.0 KiB
Swift
import SwiftUI
|
||
|
||
/// VanControl Pro am Handgelenk.
|
||
///
|
||
/// Zwei Quellen, jede dort, wo sie hingehört:
|
||
///
|
||
/// * Der **Neigungsmesser** hängt direkt an der Uhr (`WatchLevelRadio`). Die
|
||
/// Nivellierung braucht damit kein geöffnetes iPhone – und genau dafür hebt
|
||
/// man beim Rangieren den Arm.
|
||
/// * **Batterie, Solar und Kühlbox** kommen über das iPhone (`PhoneLink`),
|
||
/// weil dort die Schlüssel liegen und die Geräte nur eine Verbindung
|
||
/// zulassen.
|
||
@main
|
||
struct CamperWatchApp: App {
|
||
@State private var link = PhoneLink()
|
||
@State private var radio = WatchLevelRadio()
|
||
@Environment(\.scenePhase) private var scenePhase
|
||
|
||
var body: some Scene {
|
||
WindowGroup {
|
||
WatchRootView()
|
||
.environment(link)
|
||
.environment(radio)
|
||
.task {
|
||
link.activate()
|
||
radio.start()
|
||
// Beim Start meldet `onChange` nichts: Die Bildschirmphase
|
||
// steht schon auf „aktiv“ und ändert sich nicht mehr. Ohne
|
||
// diese Zeile bliebe der schnelle Takt des iPhones aus, bis
|
||
// die App einmal im Hintergrund war.
|
||
link.setLive(true)
|
||
}
|
||
// Die Einbaulage kommt bevorzugt aus dem Sensor selbst. Nur
|
||
// falls dort noch nichts steht – ältere Firmware, oder nie
|
||
// bestimmt –, gilt, was das iPhone meldet.
|
||
.onChange(of: link.payload?.levelDevice?.orientation) { _, orientation in
|
||
guard let orientation, !radio.hasDeviceOrientation else { return }
|
||
radio.orientation = orientation
|
||
}
|
||
}
|
||
.onChange(of: scenePhase) { _, phase in
|
||
// Beides kostet Strom und lohnt nur, solange jemand hinschaut.
|
||
// Genau das sagt die Bildschirmphase aus.
|
||
link.setLive(phase == .active)
|
||
if phase == .active { radio.start() } else { radio.stop() }
|
||
}
|
||
}
|
||
}
|