forked from fritob/Camper-Monitor
Beim ursprünglichen Merge übersehene Dateien nachziehen
Drei Dateien aus solar-integration wurden beim Zusammenführen mit dev_watch übersehen, weil sie fälschlich als "identisch zwischen den Branches" eingestuft wurden: * DemoData.isEnabled kannte nur noch den Umgebungsvariablen-Weg (CAMPER_DEMO=1). Der Schalter in den Einstellungen – der einzige Weg, Demo-Daten auf einem lokal installierten Build ohne Xcode-Verbindung einzuschalten – fehlte ganz, SettingsView.swift war nie zusammengeführt worden. * LevelSetupView.swift fehlte der komplette Abschnitt "Fahrzeuggrafik" – die Kachel-Auswahl zwischen den VehicleGraphicStyle-Varianten (Vanster/California). Das Feld existierte im Modell und wurde beim Rendern gelesen, war aber nirgends einstellbar. * DeviceCard.swift zeigte die Nivellierungs-Kachel wie jedes andere Gerät (Hauptwert + Nebenwerte) statt der grossen Front/Heck- und Links/Rechts-Anzeige mit Richtungsbuchstaben. Anlass: Im Testbuild fehlte deshalb sowohl der Demo-Modus als auch die Fahrzeuggrafik-Auswahl. Als Konsequenz systematisch alle beim Merge als "bereits identisch" eingestuften Dateien erneut gegengeprüft – keine weiteren Lücken gefunden. Build (App + Watch) und Protokoll-Tests grün. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
ed026ce580
commit
b956324234
@@ -3,18 +3,30 @@ import Foundation
|
||||
/// Füllt die App mit erfundenen Messwerten, damit sich die Ansichten ohne
|
||||
/// Fahrzeug und ohne Bluetooth prüfen lassen.
|
||||
///
|
||||
/// Nur in Debug-Builds und nur, wenn beim Start `CAMPER_DEMO=1` gesetzt ist:
|
||||
/// Nur in Debug-Builds, auf zwei Wegen einzuschalten:
|
||||
///
|
||||
/// xcrun simctl launch --terminate-running-process \
|
||||
/// booted de.fritob.VanControl
|
||||
/// # mit: SIMCTL_CHILD_CAMPER_DEMO=1 davor
|
||||
/// * Umgebungsvariable `CAMPER_DEMO=1` beim Start – praktisch im Simulator:
|
||||
///
|
||||
/// xcrun simctl launch --terminate-running-process \
|
||||
/// booted de.fritob.VanControl
|
||||
/// # mit: SIMCTL_CHILD_CAMPER_DEMO=1 davor
|
||||
///
|
||||
/// * Schalter in den Einstellungen (`SettingsView`) – der einzige Weg auf
|
||||
/// einem lokal installierten Build ohne Xcode-Verbindung, da sich dort
|
||||
/// keine Umgebungsvariable setzen lässt. Wirkt erst nach einem Neustart der
|
||||
/// App, weil `DeviceStore` und `BluetoothManager` den Stand nur beim Start
|
||||
/// lesen.
|
||||
///
|
||||
/// Im normalen Betrieb wird hiervon nichts ausgeführt.
|
||||
enum DemoData {
|
||||
|
||||
/// Schlüssel für den Einstellungen-Schalter, siehe `SettingsView`.
|
||||
static let enabledKey = "demoModeEnabled"
|
||||
|
||||
static var isEnabled: Bool {
|
||||
#if DEBUG
|
||||
return ProcessInfo.processInfo.environment["CAMPER_DEMO"] == "1"
|
||||
if ProcessInfo.processInfo.environment["CAMPER_DEMO"] == "1" { return true }
|
||||
return UserDefaults.standard.bool(forKey: enabledKey)
|
||||
#else
|
||||
return false
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,8 @@ struct DeviceCard: View {
|
||||
|
||||
if isShowingLastSettings, let snapshot {
|
||||
lastSettings(for: snapshot)
|
||||
} else if let snapshot, snapshot.primaryMetric != nil, device.role == .leveling {
|
||||
levelReadout(for: snapshot)
|
||||
} else if let snapshot, let primary = snapshot.primaryMetric {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 4) {
|
||||
Text(primary.formatted)
|
||||
@@ -115,6 +117,21 @@ struct DeviceCard: View {
|
||||
}
|
||||
}
|
||||
|
||||
/// Für die Nivellierung: Front/Heck und links/rechts nebeneinander, groß,
|
||||
/// ohne "Längsneigung"/"Querneigung"-Beschriftung – die Richtung steht ja
|
||||
/// schon im vorangestellten Buchstaben.
|
||||
private func levelReadout(for snapshot: DeviceSnapshot) -> some View {
|
||||
let pitch = snapshot.metrics.first(where: { $0.key == "pitch" })?.value
|
||||
let roll = snapshot.metrics.first(where: { $0.key == "roll" })?.value
|
||||
return HStack(spacing: 24) {
|
||||
Text(LevelDirectionFormatting.pitchTile(pitch))
|
||||
Text(LevelDirectionFormatting.rollTile(roll))
|
||||
}
|
||||
.font(.system(size: 36, weight: .semibold, design: .rounded))
|
||||
.contentTransition(.numericText())
|
||||
.foregroundStyle(snapshot.isStale ? .secondary : .primary)
|
||||
}
|
||||
|
||||
private func secondaryValues(for snapshot: DeviceSnapshot) -> some View {
|
||||
let others = snapshot.metrics
|
||||
.filter { $0.id != snapshot.primaryMetric?.id && $0.value != nil }
|
||||
|
||||
@@ -25,6 +25,8 @@ struct LevelSetupView: View {
|
||||
store.devices.first { $0.id == device.id } ?? device
|
||||
}
|
||||
|
||||
private let graphicColumns = [GridItem(.adaptive(minimum: 76), spacing: 12)]
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
@@ -80,6 +82,44 @@ struct LevelSetupView: View {
|
||||
} footer: {
|
||||
Text(calibrationHint)
|
||||
}
|
||||
|
||||
Section {
|
||||
LazyVGrid(columns: graphicColumns, spacing: 12) {
|
||||
ForEach(VehicleGraphicStyle.allCases) { style in
|
||||
Button {
|
||||
var updated = currentDevice
|
||||
updated.vehicleGraphicStyle = style
|
||||
store.update(updated)
|
||||
} label: {
|
||||
VStack(spacing: 4) {
|
||||
Image(style.sideImageName)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.padding(10)
|
||||
.frame(width: 60, height: 60)
|
||||
.background(currentDevice.vehicleGraphicStyle == style
|
||||
? Color.accentColor.opacity(0.18)
|
||||
: Color.secondary.opacity(0.08),
|
||||
in: .rect(cornerRadius: 12))
|
||||
.foregroundStyle(currentDevice.vehicleGraphicStyle == style
|
||||
? Color.accentColor : Color.primary)
|
||||
Text(style.title)
|
||||
.font(.caption2)
|
||||
.foregroundStyle(currentDevice.vehicleGraphicStyle == style
|
||||
? Color.accentColor : Color.secondary)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.accessibilityLabel(style.title)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
} header: {
|
||||
Text("Fahrzeuggrafik")
|
||||
} footer: {
|
||||
Text("Wird in der Fahrzeug-Darstellung des Neigungsmessers verwendet. "
|
||||
+ "Weitere Grafiken folgen.")
|
||||
}
|
||||
}
|
||||
.navigationTitle("Neigungsmesser einrichten")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
|
||||
@@ -4,12 +4,28 @@ import SwiftUI
|
||||
/// betrifft, steht bei diesem Gerät.
|
||||
struct SettingsView: View {
|
||||
@AppStorage(AppSettings.showDiagnosticsKey) private var showDiagnostics = false
|
||||
#if DEBUG
|
||||
@AppStorage(DemoData.enabledKey) private var demoModeEnabled = false
|
||||
#endif
|
||||
@Environment(PhoneWatchLink.self) private var watch
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
List {
|
||||
#if DEBUG
|
||||
Section {
|
||||
Toggle("Demo-Modus", isOn: $demoModeEnabled)
|
||||
} header: {
|
||||
Text("Entwicklung")
|
||||
} footer: {
|
||||
Text("Füllt die App mit erfundenen Fahrzeugen und Messwerten, um "
|
||||
+ "Ansichten ohne echte Sensoren zu prüfen. Wirkt erst nach "
|
||||
+ "einem Neustart der App – einmal beenden (im App-Umschalter "
|
||||
+ "nach oben wischen) und wieder öffnen.")
|
||||
}
|
||||
#endif
|
||||
|
||||
Section {
|
||||
Toggle("Diagnose anzeigen", isOn: $showDiagnostics)
|
||||
} header: {
|
||||
|
||||
Reference in New Issue
Block a user