Files
Camper-Monitor/VanControlComplication/LevelComplication.swift
fototeddyandClaude Sonnet 5 303a9735d0 App-Namen im iOS-Projekt auf VanControl vereinheitlichen
CamperMonitor (Haupt-Repo) und VanAligneiOS (aus dem gemergten
solar-integration-Branch) liefen unter zwei verschiedenen internen
Namen, obwohl die App nach aussen längst einheitlich "VanControl Pro"
heisst. Jetzt durchgängig VanControl:

- Ordner: CamperMonitor/, CamperMonitorWatch/, CamperMonitorComplication/,
  VanAligneiOSWidget/ → VanControl/, VanControlWatch/,
  VanControlComplication/, VanControlWidget/
- Xcode-Projekt: CamperMonitor.xcodeproj → VanControl.xcodeproj, alle
  Targets/Schemes/Produktnamen entsprechend umbenannt
- Bundle-Identifier auf Wunsch mitgeändert: de.s0.fototeddy.VanControl*
  (App noch nicht veröffentlicht); dabei auch die
  WKCompanionAppBundleIdentifier-Werte korrigiert, die noch das alte
  de.fritob-Präfix statt des tatsächlichen de.s0.fototeddy-Präfixes
  trugen
- Swift-Dateien/Typen: CamperMonitorApp → VanControlApp,
  VanAligneiOSWidget* → VanControlWidget*
- Config/*-Info.plist umbenannt, README.md/Tools/README.md/run-tests.sh
  auf die neuen Pfade angepasst

Bewusst unverändert: firmware/vanalign und alle Bezüge auf "VanAlign"
als Namen der Neigungsmesser-Hardware (eigenständiges Produkt, kein
App-Name) sowie der komplette Android/-Ordner.

Build (App, Watch, Debug) und Protokoll-Testlauf grün.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 21:25:28 +02:00

93 lines
3.4 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import SwiftUI
import WidgetKit
/// Komplikation fürs Zifferblatt: ein Tipp, und die Nivellierung steht da.
///
/// Bewusst **ohne Messwert**. Eine Komplikation läuft in einem eigenen Prozess
/// und käme an die Werte nur über eine App-Gruppe die verlangt eine bezahlte
/// Entwicklermitgliedschaft. Ein Wert, der beim Blick aufs Zifferblatt
/// womöglich Stunden alt ist, wäre ausserdem schlimmer als keiner: Man würde
/// ihm glauben.
///
/// Die Komplikation tut deshalb genau eine Sache, und die zuverlässig: Sie
/// öffnet die App auf der Nivellierung. Von dort sind die Werte live, weil die
/// Uhr den Sensor selbst anfunkt.
struct LevelComplicationEntry: TimelineEntry {
let date: Date
}
/// Nichts zu planen: Die Anzeige ändert sich nie, also ein einziger Eintrag
/// ohne Nachschub. Das kostet die Uhr auch nichts.
struct LevelComplicationProvider: TimelineProvider {
func placeholder(in context: Context) -> LevelComplicationEntry {
LevelComplicationEntry(date: .now)
}
func getSnapshot(in context: Context,
completion: @escaping (LevelComplicationEntry) -> Void) {
completion(LevelComplicationEntry(date: .now))
}
func getTimeline(in context: Context,
completion: @escaping (Timeline<LevelComplicationEntry>) -> Void) {
completion(Timeline(entries: [LevelComplicationEntry(date: .now)], policy: .never))
}
}
struct LevelComplicationView: View {
@Environment(\.widgetFamily) private var family
var body: some View {
switch family {
case .accessoryInline:
// Eine Zeile Text, mehr lässt diese Familie nicht zu.
Label("Nivellierung", systemImage: "level")
case .accessoryCorner:
Image(systemName: "level")
.font(.title2)
.widgetLabel("Nivellieren")
case .accessoryRectangular:
HStack(spacing: 6) {
Image(systemName: "level")
.font(.title3)
VStack(alignment: .leading, spacing: 0) {
Text("Nivellierung")
.font(.headline)
Text("Antippen zum Ausrichten")
.font(.caption2)
.foregroundStyle(.secondary)
}
}
default:
// Rund auf dem Zifferblatt der knappste Platz, also nur das
// Symbol, gross genug zum Treffen.
ZStack {
AccessoryWidgetBackground()
Image(systemName: "level")
.font(.title2)
}
}
}
}
@main
struct LevelComplication: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(kind: "de.fritob.VanControl.complication.level",
provider: LevelComplicationProvider()) { _ in
LevelComplicationView()
// Der Tipp landet nicht irgendwo in der App, sondern auf der
// Nivellierung dafür wertet die App diese Adresse aus.
.widgetURL(WatchDeepLink.level)
.containerBackground(.clear, for: .widget)
}
.configurationDisplayName("Nivellierung")
.description("Öffnet die Nivellierung direkt vom Zifferblatt.")
.supportedFamilies([.accessoryCircular, .accessoryCorner,
.accessoryInline, .accessoryRectangular])
}
}