From b1ffbe324a56bff84b583d6790e02bad14886b3b Mon Sep 17 00:00:00 2001 From: fototeddy Date: Thu, 10 Sep 2026 18:35:14 +0200 Subject: [PATCH] =?UTF-8?q?Libelle:=20Blase=20wandert=20zur=20h=C3=B6heren?= =?UTF-8?q?=20Seite,=20einheitlich=20auf=20allen=20Anzeigen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Die drei Libellen widersprachen sich: Die Live Activity liess die Blase bei positivem Pitch nach unten wandern – mit dem Kommentar "wie bei der echten Wasserwaage in der App" –, waehrend iPhone und Uhr genau das Gegenteil taten. Gemeint war immer eine Draufsicht mit Fahrtrichtung oben, in der die Blase zur hoeheren Seite ausschlaegt: Steht das Heck hoeher, gehoert sie nach hinten, also nach unten. iPhone und Uhr ziehen jetzt nach. Die Android-Fassung bleibt vorerst bei der alten Richtung. Dazu `shortInstructions`: dieselbe Aussage wie `instruction`, aber in kurzen Zeilen statt einem Satz. Auf schmalen Anzeigen passt "Heck steht hoeher, links steht hoeher" in keine lesbare Zeile. Beide stehen nebeneinander, damit die Vorzeichen nicht auseinanderlaufen. Co-Authored-By: Claude Opus 5 --- Shared/Models/LevelState.swift | 19 +++++++++++++++++++ VanControl/Views/LevelView.swift | 8 +++++--- VanControlWatch/Views/WatchBubble.swift | 7 ++++--- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Shared/Models/LevelState.swift b/Shared/Models/LevelState.swift index 688a9cb..6f78501 100644 --- a/Shared/Models/LevelState.swift +++ b/Shared/Models/LevelState.swift @@ -65,6 +65,25 @@ struct LevelState: Equatable, Codable, Sendable { return parts.joined(separator: ", ") } + /// Dasselbe wie ``instruction``, aber in kurzen Zeilen statt einem Satz – + /// für schmale Anzeigen wie das CarPlay-Display, wo "Heck steht höher, + /// rechts steht höher" nicht in eine lesbare Zeile passt. + /// + /// Die Vorzeichen müssen zu ``instruction`` passen; beide stehen deshalb + /// nebeneinander. + var shortInstructions: [String] { + guard let pitch, let roll else { return [] } + if isLevel { return ["Steht eben"] } + var parts: [String] = [] + if abs(pitch) > Self.levelTolerance { + parts.append(pitch > 0 ? "Heck höher" : "Front höher") + } + if abs(roll) > Self.levelTolerance { + parts.append(roll > 0 ? "Rechts höher" : "Links höher") + } + return parts + } + func snapshot(deviceID: UUID, rssi: Int?) -> DeviceSnapshot { var snapshot = DeviceSnapshot(deviceID: deviceID, timestamp: Date(), rssi: rssi) snapshot.metrics = [ diff --git a/VanControl/Views/LevelView.swift b/VanControl/Views/LevelView.swift index 869cabb..12c8482 100644 --- a/VanControl/Views/LevelView.swift +++ b/VanControl/Views/LevelView.swift @@ -75,9 +75,11 @@ struct LevelBubble: View { Circle() .fill(bubbleColor) .frame(width: bubble, height: bubble) - // Positiver Pitch heisst: das Heck steht höher, die Blase - // wandert also nach oben – in der Ansicht nach hinten. - .offset(x: offsetX, y: -offsetY) + // Draufsicht mit Fahrtrichtung oben: Positiver Pitch heisst, + // das Heck steht höher – die Blase wandert nach hinten, also + // nach unten. Wie bei einer echten Wasserwaage, die zur + // höheren Seite ausschlägt. + .offset(x: offsetX, y: offsetY) .animation(.spring(duration: 0.35), value: offsetX) .animation(.spring(duration: 0.35), value: offsetY) .opacity(pitch == nil && roll == nil ? 0.25 : 1) diff --git a/VanControlWatch/Views/WatchBubble.swift b/VanControlWatch/Views/WatchBubble.swift index 65a9a87..79e8f92 100644 --- a/VanControlWatch/Views/WatchBubble.swift +++ b/VanControlWatch/Views/WatchBubble.swift @@ -30,10 +30,11 @@ struct WatchBubble: View { Circle() .fill(color) .frame(width: bubble, height: bubble) - // Positiver Pitch heisst: das Heck steht höher, die Blase - // wandert nach oben – in der Ansicht also nach hinten. + // Draufsicht mit Fahrtrichtung oben: Positiver Pitch heisst, + // das Heck steht höher – die Blase wandert nach hinten, also + // nach unten. .offset(x: clamped(roll) / range * travel, - y: -clamped(pitch) / range * travel) + y: clamped(pitch) / range * travel) .animation(.spring(duration: 0.3), value: pitch) .animation(.spring(duration: 0.3), value: roll) .opacity(pitch == nil && roll == nil ? 0.25 : 1)