Compare commits
1
Commits
5fec4a55dd
...
dev_watch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
812874baef |
@@ -262,6 +262,13 @@ final class BluetoothManager: NSObject {
|
|||||||
for snapshot in DemoData.snapshots() {
|
for snapshot in DemoData.snapshots() {
|
||||||
snapshots[snapshot.deviceID] = snapshot
|
snapshots[snapshot.deviceID] = snapshot
|
||||||
linkStates[snapshot.deviceID] = .live
|
linkStates[snapshot.deviceID] = .live
|
||||||
|
// Die Kühlbox wird nur beim Öffnen verbunden – im Vorführbetrieb
|
||||||
|
// steht sie deshalb wie im Alltag auf „zuletzt gestellt“.
|
||||||
|
if snapshot.deviceID == DemoData.fridge.id,
|
||||||
|
let settings = DemoData.fridgeState.settings {
|
||||||
|
linkStates[snapshot.deviceID] = .idle
|
||||||
|
snapshots[snapshot.deviceID] = settings.snapshot(deviceID: snapshot.deviceID)
|
||||||
|
}
|
||||||
if let value = snapshot.primaryMetric?.value {
|
if let value = snapshot.primaryMetric?.value {
|
||||||
history[snapshot.deviceID] = DemoData.history(for: snapshot.deviceID, around: value)
|
history[snapshot.deviceID] = DemoData.history(for: snapshot.deviceID, around: value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ struct DeviceCard: View {
|
|||||||
VStack(alignment: .leading, spacing: 12) {
|
VStack(alignment: .leading, spacing: 12) {
|
||||||
header
|
header
|
||||||
|
|
||||||
if let snapshot, let primary = snapshot.primaryMetric {
|
if isShowingLastSettings, let snapshot {
|
||||||
|
lastSettings(for: snapshot)
|
||||||
|
} else if let snapshot, let primary = snapshot.primaryMetric {
|
||||||
HStack(alignment: .firstTextBaseline, spacing: 4) {
|
HStack(alignment: .firstTextBaseline, spacing: 4) {
|
||||||
Text(primary.formatted)
|
Text(primary.formatted)
|
||||||
.font(.system(size: 44, weight: .semibold, design: .rounded))
|
.font(.system(size: 44, weight: .semibold, design: .rounded))
|
||||||
@@ -54,6 +56,65 @@ struct DeviceCard: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ob hier der zuletzt gestellte Stand steht statt Messwerten.
|
||||||
|
private var isShowingLastSettings: Bool {
|
||||||
|
device.role.connectsOnDemand && linkState != .live
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Die Kachel der Kühlbox, solange sie nicht verbunden ist.
|
||||||
|
///
|
||||||
|
/// Hier steht kein Messwert, sondern was zuletzt eingestellt war – also
|
||||||
|
/// gehört „Soll“ dazu. Ohne das läse man die Zahl als Innentemperatur, und
|
||||||
|
/// genau dieser Irrtum wäre teuer.
|
||||||
|
private func lastSettings(for snapshot: DeviceSnapshot) -> some View {
|
||||||
|
HStack(alignment: .top, spacing: 12) {
|
||||||
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
|
Text(snapshot.metrics.count > 1 ? "Soll links" : "Soll")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
HStack(alignment: .firstTextBaseline, spacing: 4) {
|
||||||
|
Text(snapshot.primaryMetric?.formatted ?? "–")
|
||||||
|
.font(.system(size: 44, weight: .semibold, design: .rounded))
|
||||||
|
Text(snapshot.primaryMetric?.unit ?? "")
|
||||||
|
.font(.title3.weight(.medium))
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let right = snapshot.metrics.first(where: { $0.key == "target_right" }),
|
||||||
|
right.value != nil {
|
||||||
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
|
Text("Soll rechts")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
Text(right.formattedWithUnit)
|
||||||
|
.font(.title2.weight(.semibold))
|
||||||
|
.monospacedDigit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(minLength: 0)
|
||||||
|
modeBadge(snapshot.state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Betriebsart als Schild: Auf der Kachel ist Platz, und ob die Box läuft
|
||||||
|
/// oder aus ist, ist die zweite Frage nach dem Sollwert.
|
||||||
|
@ViewBuilder
|
||||||
|
private func modeBadge(_ state: String?) -> some View {
|
||||||
|
if let state {
|
||||||
|
let isOff = state == "Aus"
|
||||||
|
Text(state)
|
||||||
|
.font(.title3.weight(.semibold))
|
||||||
|
.foregroundStyle(isOff ? Color.secondary : Color.accentColor)
|
||||||
|
.padding(.horizontal, 14)
|
||||||
|
.padding(.vertical, 8)
|
||||||
|
.background(isOff ? Color.secondary.opacity(0.15)
|
||||||
|
: Color.accentColor.opacity(0.15),
|
||||||
|
in: .rect(cornerRadius: 12))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func secondaryValues(for snapshot: DeviceSnapshot) -> some View {
|
private func secondaryValues(for snapshot: DeviceSnapshot) -> some View {
|
||||||
let others = snapshot.metrics
|
let others = snapshot.metrics
|
||||||
.filter { $0.id != snapshot.primaryMetric?.id && $0.value != nil }
|
.filter { $0.id != snapshot.primaryMetric?.id && $0.value != nil }
|
||||||
@@ -76,7 +137,7 @@ struct DeviceCard: View {
|
|||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var footer: some View {
|
private var footer: some View {
|
||||||
if device.role.connectsOnDemand, linkState != .live, let snapshot {
|
if isShowingLastSettings, let snapshot {
|
||||||
// Kein Messwert, sondern der zuletzt gestellte Stand. Das gehört
|
// Kein Messwert, sondern der zuletzt gestellte Stand. Das gehört
|
||||||
// dazugeschrieben, sonst liest man ihn als aktuelle Temperatur.
|
// dazugeschrieben, sonst liest man ihn als aktuelle Temperatur.
|
||||||
Text(lastSetText(snapshot))
|
Text(lastSetText(snapshot))
|
||||||
@@ -104,10 +165,11 @@ struct DeviceCard: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Was unter einem Gerät steht, das nur beim Öffnen verbunden wird.
|
/// Was unter einem Gerät steht, das nur beim Öffnen verbunden wird.
|
||||||
|
///
|
||||||
|
/// Der Hinweis aufs Verbinden steht vorn: Er erklärt, warum hier kein
|
||||||
|
/// Messwert steht, und das ist die Frage, die sich zuerst stellt.
|
||||||
private func lastSetText(_ snapshot: DeviceSnapshot) -> String {
|
private func lastSetText(_ snapshot: DeviceSnapshot) -> String {
|
||||||
let age = relativeUpdate(snapshot.timestamp)
|
"Verbindet erst beim Öffnen · zuletzt gestellt \(relativeUpdate(snapshot.timestamp))"
|
||||||
guard let state = snapshot.state else { return "Zuletzt gestellt \(age)" }
|
|
||||||
return "\(state) · zuletzt gestellt \(age)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// „vor 3 Minuten“ statt einer Uhrzeit – auf der Kachel zählt das Alter.
|
/// „vor 3 Minuten“ statt einer Uhrzeit – auf der Kachel zählt das Alter.
|
||||||
|
|||||||
Reference in New Issue
Block a user