forked from fritob/Camper-Monitor
Libelle: Blase wandert zur höheren Seite, einheitlich auf allen Anzeigen
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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8401f62d91
commit
b1ffbe324a
@@ -65,6 +65,25 @@ struct LevelState: Equatable, Codable, Sendable {
|
|||||||
return parts.joined(separator: ", ")
|
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 {
|
func snapshot(deviceID: UUID, rssi: Int?) -> DeviceSnapshot {
|
||||||
var snapshot = DeviceSnapshot(deviceID: deviceID, timestamp: Date(), rssi: rssi)
|
var snapshot = DeviceSnapshot(deviceID: deviceID, timestamp: Date(), rssi: rssi)
|
||||||
snapshot.metrics = [
|
snapshot.metrics = [
|
||||||
|
|||||||
@@ -75,9 +75,11 @@ struct LevelBubble: View {
|
|||||||
Circle()
|
Circle()
|
||||||
.fill(bubbleColor)
|
.fill(bubbleColor)
|
||||||
.frame(width: bubble, height: bubble)
|
.frame(width: bubble, height: bubble)
|
||||||
// Positiver Pitch heisst: das Heck steht höher, die Blase
|
// Draufsicht mit Fahrtrichtung oben: Positiver Pitch heisst,
|
||||||
// wandert also nach oben – in der Ansicht nach hinten.
|
// das Heck steht höher – die Blase wandert nach hinten, also
|
||||||
.offset(x: offsetX, y: -offsetY)
|
// 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: offsetX)
|
||||||
.animation(.spring(duration: 0.35), value: offsetY)
|
.animation(.spring(duration: 0.35), value: offsetY)
|
||||||
.opacity(pitch == nil && roll == nil ? 0.25 : 1)
|
.opacity(pitch == nil && roll == nil ? 0.25 : 1)
|
||||||
|
|||||||
@@ -30,10 +30,11 @@ struct WatchBubble: View {
|
|||||||
Circle()
|
Circle()
|
||||||
.fill(color)
|
.fill(color)
|
||||||
.frame(width: bubble, height: bubble)
|
.frame(width: bubble, height: bubble)
|
||||||
// Positiver Pitch heisst: das Heck steht höher, die Blase
|
// Draufsicht mit Fahrtrichtung oben: Positiver Pitch heisst,
|
||||||
// wandert nach oben – in der Ansicht also nach hinten.
|
// das Heck steht höher – die Blase wandert nach hinten, also
|
||||||
|
// nach unten.
|
||||||
.offset(x: clamped(roll) / range * travel,
|
.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: pitch)
|
||||||
.animation(.spring(duration: 0.3), value: roll)
|
.animation(.spring(duration: 0.3), value: roll)
|
||||||
.opacity(pitch == nil && roll == nil ? 0.25 : 1)
|
.opacity(pitch == nil && roll == nil ? 0.25 : 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user